All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.codename1.impl.ios.ZoozPurchase Maven / Gradle / Ivy

/*
 * Copyright (c) 2012, Codename One and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Codename One designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *  
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 * 
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 * 
 * Please contact Codename One through http://www.codenameone.com/ if you 
 * need additional information or have any questions.
 */
package com.codename1.impl.ios;

import com.codename1.io.Log;
import com.codename1.payment.*;
import com.codename1.processing.Result;
import com.codename1.ui.CN;
import com.codename1.ui.Display;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * Implementation of the purchase API
 *
 * @author Shai Almog
 */
class ZoozPurchase extends Purchase implements Runnable {

    private String purchaseId = null;
    private static final Object LOCK = new Object();
    private static boolean completed = false;
    private static boolean fetchProductsFailed;
    private static boolean fetchProductsComplete;
    private static String fetchProductsFailedMessage;

    private IOSNative nativeInstance;
    private IOSImplementation ioImpl;
    private static String transactionId;
    private static double amount;
    private static String errorMessage;
    private PurchaseCallback callback;
    public ZoozPurchase(IOSImplementation ioImpl, IOSNative nativeInstance, PurchaseCallback callback) {
        this.nativeInstance = nativeInstance;
        this.ioImpl = ioImpl;
        this.callback = callback;
    }

    @Override
    public String getStoreCode() {
        return Receipt.STORE_CODE_ITUNES;
    }

    public boolean isManagedPaymentSupported() {
        return nativeInstance.canMakePayments();
    }

    public boolean isItemListingSupported() {
        return true;
    }

    static void paymentSuccessWithResponse(String t, float total) {
        transactionId = t;
        amount = total;
        completed = true;
        synchronized(LOCK) {
            LOCK.notify();
        }
    }

    static void paymentCanceledOrFailed(String error) {
        transactionId = null;
        errorMessage = error;
        completed = true;
        synchronized(LOCK) {
            LOCK.notify();
        }
    }

    static void fetchProductsCanceledOrFailed(String error) {
        fetchProductsFailedMessage = error;
        fetchProductsFailed = true;
    }

    static void fetchProductsComplete(){
        fetchProductsComplete=true;
    }

    public synchronized Product[] getProducts(String[] skus) {
        int numSkus = skus.length;
        final Product[] p = new Product[numSkus];
        for(int iter = 0; iter < numSkus; iter++) {
            p[iter] = new Product();
        }
        fetchProductsFailed = false;
        fetchProductsComplete = false;
        nativeInstance.fetchProducts(skus, p);

        // wait for request to complete
        Display.getInstance().invokeAndBlock(new Runnable() {
            @Override
            public void run() {
                while(!fetchProductsFailed && !fetchProductsComplete) {
                    try {
                        Thread.currentThread().sleep(10);
                    } catch (InterruptedException ex) {
                    }
                }
            }
        });
        if(fetchProductsFailed) {
            Log.e(new IOException("Failed to fetch products: " + fetchProductsFailedMessage));
            return null;
        }
        return p;
    }

    public boolean wasPurchased(String sku) {
        return ioImpl.getPurchased().contains(sku);
    }

    public void purchase(String sku) {
        nativeInstance.purchase(sku);
    }

    @Override
    public void purchase(String sku, PromotionalOffer promotionalOffer) {
        if (promotionalOffer == null) {
            nativeInstance.purchase(sku);
            return;
        }

        if (!(promotionalOffer instanceof ApplePromotionalOffer)) {
            throw new RuntimeException("Unsupported promotional offer.  Expected ApplePromotionalOffer but received " + promotionalOffer.getClass());
        }

        nativeInstance.purchase(skuAndPromotionalOfferToJSON(sku, (ApplePromotionalOffer) promotionalOffer));
    }

    public void subscribe(String sku) {
        if (getReceiptStore() != null) {
            purchase(sku);
            return;
        }
        super.subscribe(sku);
    }

    @Override
    public void subscribe(String sku, PromotionalOffer promotionalOffer) {
        if (promotionalOffer == null) {
            subscribe(sku);
            return;
        }

        if (!(promotionalOffer instanceof ApplePromotionalOffer)) {
            throw new RuntimeException("Unsupported promotional offer.  Expected ApplePromotionalOffer but received " + promotionalOffer.getClass());
        }

        nativeInstance.purchase(skuAndPromotionalOfferToJSON(sku, (ApplePromotionalOffer) promotionalOffer));
    }

    public boolean isSubscriptionSupported() {
        return getReceiptStore() != null;
    }

    public boolean isUnsubscribeSupported() {
        return false;
    }

    @Override
    public boolean isManualPaymentSupported() {
        return true;
    }

    @Override
    public String pay(double amount, final String currency, String invoiceNumber) {
        String zoozAppKey = Display.getInstance().getProperty("ZoozAppKey", "");
        boolean isSandBox = Display.getInstance().getProperty("ZoozSandBox", "true").equals("true");
        nativeInstance.zoozPurchase(amount, currency, zoozAppKey, isSandBox, invoiceNumber);
        Display.getInstance().invokeAndBlock(this);
        // use call serially so the purchase callback happens on the 
        // next EDT loop AFTER the value was returned 
        Display.getInstance().callSerially(new Runnable() {
            @Override
            public void run() {
                if (callback != null) {
                    if (errorMessage != null) {
                        callback.paymentFailed(purchaseId, errorMessage);
                    } else {
                        // iOS port doesn't return the currency in its callback
                        callback.paymentSucceeded(purchaseId, ZoozPurchase.this.amount, currency);
                    }
                }
            }
        });
        return transactionId;
    }

    @Override
    public String pay(double amount, String currency) {
        return pay(amount, currency, "N/A");
    }

    @Override
    public void run() {
        synchronized (LOCK) {
            while (!completed) {
                try {
                    LOCK.wait();
                } catch (InterruptedException ex) {
                }
            }
        }
    }

    @Override
    public boolean isRestoreSupported() {
        return true;
    }

    @Override
    public void restore() {
        nativeInstance.restorePurchases();
    }

    @Override
    public boolean isManageSubscriptionsSupported() {
        return true;
    }

    @Override
    public void manageSubscriptions(String sku) {
        CN.execute("itms-apps://apps.apple.com/account/subscriptions");
    }

    private String skuAndPromotionalOfferToJSON(String sku, ApplePromotionalOffer promotionalOffer) {
        Map payload = new HashMap();
        payload.put("sku", sku);
        Map promo = new HashMap();
        promo.put("offerIdentifier", promotionalOffer.getOfferIdentifier());
        promo.put("keyIdentifier", promotionalOffer.getKeyIdentifier());
        promo.put("nonce", promotionalOffer.getNonce());
        promo.put("signature", promotionalOffer.getSignature());
        promo.put("timestamp", promotionalOffer.getTimestamp());
        payload.put("promotionalOffer", promo);
        return Result.fromContent(payload).toString().trim();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy