# Documentations


# Access to Private and Public S3 bucket

You can now access directly to your Parse Server media files (jpg,png, mp3, doc, ppt, key, pdf....) on your S3 private bucket. \
And publish a HTML website on you Public S3 storage.

![](/files/-LTwV1vHeCMCv2fRup71)

Exemple with  CyberDuck software and the Public Bucket.

1\) Install a cyberduck software

![](/files/-LTwXcJSCJ3Omz68E-nj)

2\) Go to Symbyoz Console >> Project >> Cloud Storage and copy past **Access Key** and **Secret Key**

![](/files/-LTwXeuVtn_JvhJjD4dq)

Drag & drop directly you HTML, CSS, Javascript, images files to CyberDuck

![](/files/-LTwXhd1U2hQ99MWw_oJ)

Finish !! The files are now online.


# Create manual database Backup

You can now create a backup of your database and your back-office structure. \
And save on a hard-disk or use for duplicate you project.

You can also import a database from another Parse-server like Back4apps, Node-Chef or Sashido.

![](/files/-LTwSIj2nhOOpXyLRxpu)

![](/files/-LTwSNqVdjXG6o_ABDS1)


# Parse Live Query on Symbyoz

PFQuery is one of the key concepts for Parse. It allows you to retrieves PFObject  by specifying some conditions, making it easy to build apps such as a dashboard, a todo list or even some strategy games. However, PFQuery is based on a **PULL model**, which is not suitable for apps that need real-time support.

Suppose you are building an app that allows multiple users to edit the same file at the same time like a Chat. \
PFQuery would not be an ideal tool since you can not know when to query from the server to get the updates.

To solve this problem, we introduce **Parse LiveQuery**. This tool allows you **to subscribe to a PFQuery** you are interested in. Once subscribed, the server will notify clients whenever a PFObject that matches the PFQuery is created or updated, in real-time. <br>

Live Query is a **PUSH model.**

![](/files/-LTwOQkZLsyr041mczLd)

{% tabs %}
{% tab title="Java" %}

```java
public void getLiveMessages()
{
        ParseLiveQueryClient parseLiveQueryClient = ParseLiveQueryClient.Factory.getClient();

        ParseQuery<ParseObject> queryMessage = ParseQuery.getQuery("Messages");

        SubscriptionHandling<ParseObject> messageChannel = parseLiveQueryClient.subscribe(queryMessage);

        // CHOOS ONLY ONE BETWEEN handleEvent and handleEvents
        messageChannel.handleEvents(new SubscriptionHandling.HandleEventsCallback<ParseObject>()
        {
            @Override
            public void onEvents(ParseQuery<ParseObject> query, SubscriptionHandling.Event event, ParseObject object)
            {
                // Triggered when an object from the class Messages is created, updated or deleted
                // use method handleEvent instead of handleEvents to get ONLY created object
            }
        });

}
```

{% endtab %}
{% endtabs %}


# Symbyoz back-office "white mark"

You can now customize your back-office look and field

* Add Custom Logo
* Select language between French / English (others coming soon)
* Select Top bar and Left Menu color

![](/files/-LRoRGgqF0WHEjPqDTC8)

![](/files/-LRoTrzJeOX3GUoMb8zR)

![](/files/-LRq3pYe3QaqEoapAner)

![](/files/-LRolr1MgkdV4Ddllofs)


# Cloud Code is now available in a Console

You can write or import your Javascript server code directly inside the console now.

![](/files/-LRlc43h3epYU_f4cgkY)

![](/files/-LRlc9zzThn9Xj3XFGkw)

You can see example of Cloud Code in  SOURCE CODE EXAMPLES  >> [Cloud Code](https://docs.symbyoz.io/code_examples/cloud-code)


# How to create a new project

See all steps for create project in less than 10 minutes

Create an account  on <https://console.symbyoz.io>

![](/files/-LRkWjuMU-hLTl3pLL-K)

Click to **Add New Project**

![](/files/-LRlZrIyLl-dZKQcjzfx)

Choose your server configuration. Start with BASIC, you can easily update later.

![](/files/-LRkX0I2mDNht91f5iGH)

Give name and description to your Project - Choose server location and options

![](/files/-LRkX7NoUWcPEoggrYqu)

Add your credit card information \
Choose to pay monthly or anualy

![](/files/-LRkXGklM3aVk7sNh09F)

The install take between 5 to 10 min for create your project

![](/files/-LRkX_ERQVCdL2FSdcjF)

Your project is ready, Click to **Modify** for see the project details

![](/files/-LRkWuBLJlMCpwCRCaRg)

AppID, Key, Urls, Login & Password are available here\
You can also   :

* Restart the server,
* Re-install the server,
* Delete the server,
* Configure all services (Twilio, MailGun, Stripe, Push-notification...)
* Customize the back-office (logo, color, language)
* Add you own javascript server code with Cloud-code

{% hint style="info" %}
When you choose to restart or re-install the server, you don't loose your datas from the database or your cloud code.
{% endhint %}

![](/files/-LRkY9hRVV_CxQdkCpFC)


# How to create a custom module

First go to [console.symbyoz.io](https://console.symbyoz.io)

![](/files/-LRln26ZS3m5ek9I3bSz)

If you don't know your back-office login & password click to "**Modify**" and copy the URL to a new page.

![](/files/-LRlndkD8ZzlgSLRv8Ei)

Connect to the back-office

![](/files/-LRlo-iK5EddLVTQq5PS)

On a left menu, go to : **Configuration** >> **Modules**

![](/files/-LRlqXO0nVlxXbl0p5iy)

Click on green button **Add new**

![](/files/-LRltFZkHhUW7Pre7Vq6)

Add Module Title (name appear in Back-office)\
Add Module Name (database classe name)\
Click on green button **Create**

![](/files/-LRlqz65Zbn52tWVFuyo)

Your module is now visible in module liste. \
Now we must add custom field inside\
Click to yellow button **Edit**

![](/files/-LRlsyll-_vTWiAhDo5-)

Click on **Module custom fields**&#x20;

![](/files/-LRluBv3mdJaqc77eiUc)

Here yo can see all fields inside your module. \
*Id*, *Created at* and *Updated at* are default fields from mongoDB document.\
Click to **Add New button** for add a new custom field

![](/files/-LRlvJiXAjaoV_s4ZbdW)

* [ ] Add a Field name
* [ ] Add a Field title
* [ ] Choose input type inside 25 customs fields type.
* [ ] Click to green button **Create**&#x20;

{% hint style="info" %}
The database, only manages 9 types of fields. \
You can change the type of a field in the back-office at any time, as long as it remains in the same database category (Array, String, Date, Number, File, Pointer, Boolean,  ...) \
Exemple : \
You can change **Text** to **Email** or **Phone...**\
But you cannot change **Text** to **Array**
{% endhint %}

![](/files/-LRlzDTaaowg2chvQYDw)

You can organize the display order of fields by Drag & Drop\
You can choose is a field is :&#x20;

* Compulsory
* Visible only by super-admin in back-office
* Unique
* Visible in filter
* Visible in module form (create or edit)
* Visible in module listing

{% hint style="info" %}
For generate your custom module you must click on  button  **Generate**
{% endhint %}

![](/files/-LRm0aSPmudYOD6HZj6Y)

Your custom module is now ready to use\
You can acces directly from left menu

![](/files/-LRm2CQ0pbloL45D_wuM)

![](/files/-LRm2Eg6l8zljlTg-u4x)


# How to manage left menu

With Symbyoz, you can easily organize your business modules in the menu.

On a left Menu go to **Configuration** >> **Module groups**

![](/files/-LRmAc01MZWnReg1vSUU)

Click to **Add New**

![](/files/-LRmB8ZpjkDHf9pe9ezv)

* [ ] Write a Module group name
* [ ] Select the Modules inside a list
* [ ] Choose the icon

![](/files/-LRmCcHMNPUvzwvngurG)

![](/files/-LRmCgPTObsloz8r_uNu)

Your new module group is now visible in Left Menu

![](/files/-LRmDFoDSNXRCtxGzpBk)


# How to manage admin user rights

You can easily manage user rights in back-office

First go to : **Configuration** >> **Users**

![](/files/-LRmGcQCdjjzCBgx5FZ0)

Click to **Add new**

![](/files/-LRmGsdZVE--bw7Z-0vO)

By default new user role is **User with no rights**\
Choose role **Administrator**  and select in left side the rights module by module

* Listing (can see records)
* See (can see record detail)
* Create (can create new record)
* Edit (can modify a existing record)
* Erase (can delete a record)
* All rights

{% hint style="info" %}
If you select **link to an app user,** Symbyoz create automatically a user inside \_User table with same login & password than this admin. \
This option is very important if you use role & ACL, and if you want limit the right of this user on records in authorized modules.
{% endhint %}


# Connect to iOS app

{% tabs %}
{% tab title="Swift" %}

```swift
import Parse

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
    {
        self.setupParse()
        return true
    }
    
    func setupParse()
    {
        Parse.setLogLevel(PFLogLevel.debug)
        Parse.enableLocalDatastore()
        let parseConfiguration = ParseClientConfiguration(block:
        {
            (ParseMutableClientConfiguration) -> Void in
            ParseMutableClientConfiguration.applicationId = "xxxxxxxxxx"
            ParseMutableClientConfiguration.clientKey = "yyyyyyyyy"
            ParseMutableClientConfiguration.server = "https://xxxx.parse-symbyoz.com/parse"
            ParseMutableClientConfiguration.isLocalDatastoreEnabled = true
        })
        Parse.initialize(with: parseConfiguration)
    }
}




    
```

{% endtab %}
{% endtabs %}


# Connect to Android app

https\://docs.parseplatform.org/android/guide/#getting-started

## Install `Parse-SDK-Android`

Open your project's `build.gradle` file (**not** the module file) and add this dependency,

```java
allprojects {
	repositories {
		...
		maven { url "https://jitpack.io" }
	}
}
```

Then open your module `build.gradle` file and add the Parse library \
(with the latest version being[![](https://jitpack.io/v/parse-community/Parse-SDK-Android.svg)](https://jitpack.io/#parse-community/Parse-SDK-Android))

```java
dependencies {
    implementation "com.github.parse-community.Parse-SDK-Android:parse:1.18.5"
}
```

## Initialize Parse

Setup Parse using your server configuration:

{% code title="MyApp.java" %}

```java
import com.parse.Parse;
import android.app.Application;

public class MyApp extends Application 
{
  @Override
  public void onCreate() 
  {
    super.onCreate();
    
    Parse.initialize(new Parse.Configuration.Builder(this)
      .applicationId("YOUR_APP_ID")
      .clientKey("YOUR_CLIENT_KEY")
      .server("https://xxxx.parse-symbyoz.com/parse/")
      .enableLocalDataStore()
      .build()); 
  }
}
```

{% endcode %}

The custom `Application` class must be registered in `AndroidManifest.xml`

{% code title="AndroidManifest.xml" %}

```markup
<application
   android:name=".MyApp"
   ...>
   ...
 </application>
```

{% endcode %}


# Create & Save Object

Storing data on Symbyoz is built around **Parse** and his `ParseObject`. \
Each `ParseObject`contains key-value pairs of JSON-compatible data. This data is schemaless, which means that you don’t need to specify ahead of time what keys exist on each `ParseObject`. &#x20;

If you want to have a structured model of your object, you can do it so by registering what we call [Subclasses](/code_examples/subclasses) (see more infos on [this page](/code_examples/subclasses)).

## Simple Way

{% tabs %}
{% tab title="Java" %}

```java
import com.parse.ParseObject;

public void createObject()
{
    ParseObject object = new ParseObject("ClassName");
    // object.put(key, value);
    object.put("age", 37);
    object.put("userName", "John Doe");
    object.put("isFunny", false);
    
    object.saveInBackground();
}
```

{% endtab %}

{% tab title="Swift" %}

```swift
import Parse

class testVC: UIViewController
{
    override func viewDidLoad()
    {
        super.viewDidLoad()
        self.createObjet()
    }


    func createObjet()
    {
        let newObject = PFObject.init(className:"test")
        newObject["TitleA"] = "valueA"
        newObject["isBoolean"] = true
        newObecjt["pointer"] = PFUser.current()        
        newObject.saveInBackground()   
    }
}
```

{% endtab %}
{% endtabs %}

## With Callback

{% tabs %}
{% tab title="Java" %}

```java
import com.parse.ParseException;
import com.parse.ParseObject;
import com.parse.SaveCallback;

public void createObject()
{
        ParseObject object = new ParseObject("ClassName");
        // object.put(key, value);
        object.put("age", 37);
        object.put("userName", "John Doe");
        object.put("isFunny", false);

        object.saveInBackground(new SaveCallback()
        {
            @Override
            public void done(ParseException e) 
            {
                
            }
        });
}
```

{% endtab %}

{% tab title="Swift" %}

```swift
import Parse
​
class testVC: UIViewController
{
    override func viewDidLoad()
    {
        super.viewDidLoad()
        self.createObjet()
    }
​
​
    func createObjet()
    {
        let newObject = PFObject.init(className:"test")
        newObject["TitleA"] = "valueA"
        newObject["isBoolean"] = true
        newObecjt["pointer"] = PFUser.current()        
        newObject.saveInBackground(block:
        {
            (isSuccess, error) in
                if let error = error
                {   
                    print (error.localizedDescription)
                }
                else 
                {
                    if (isSuccess)
                    {
                        // Do something                    
                    }
                }
        })
    }
}
```

{% endtab %}
{% endtabs %}


# Get Object

Get a whole `Object` using a [**`Query`**](/code_examples/queries):

{% tabs %}
{% tab title="Java" %}

```java
import com.parse.ParseObject;
import com.parse.ParseQuery;
import com.parse.GetCallback;
import com.parse.ParseException;

public void getObject()
{
  ParseQuery<ParseObject> query = ParseQuery.getQuery("ClassName");
  query.getInBackground("objectId", new GetCallback<ParseObject>() 
  {
    public void done(ParseObject object, ParseException e) 
    {
      if (e == null) 
      {
        // your object will be returned here
      } 
      else 
      {
        // something went wrong, check the exception for more infos
      } 
    }
  });
}
```

{% endtab %}

{% tab title="Swift" %}

```swift
import Parse
​
class testVC: UIViewController
{
    override func viewDidLoad()
    {
        super.viewDidLoad()
        self.getObjet(id:"AB1234")
    }
​
​
    func getObjet(id:String)
    {
        let query = PFQuery.init(className: "ClassName")
        query.getObjectInBackground(withId: id)  
    }
}
```

{% endtab %}
{% endtabs %}

Get the values out of the `Object`:

{% tabs %}
{% tab title="Java" %}

```java
import com.parse.ParseObject;

public void getSomeValues(ParseObject object)
{
    int age = object.getInt("age");
    String userName = object.getString("userName");
    boolean isFunny = object.getBoolean("isFunny");
    ParseObject = object.getParseObject("customObject");
}
```

{% endtab %}

{% tab title="Swift" %}

{% endtab %}
{% endtabs %}

Special values that have their own accessors:

{% tabs %}
{% tab title="Java" %}

```java
import com.parse.ParseObject;

public void getSpecialValues(ParseObject object)
{
    String objectId = object.getObjectId();
    Date updatedAt = object.getUpdatedAt();
    Date createdAt = object.getCreatedAt();
    ParseACL acl = object.getACL();
}
```

{% endtab %}

{% tab title="Swift" %}

```
```

{% endtab %}
{% endtabs %}

Refresh an object that you already have in memory with the latest data:

{% tabs %}
{% tab title="Java" %}

```java
import com.parse.ParseObject;
import com.parse.GetCallback;
import com.parse.ParseException;

public void refreshObject(ParseObject object)
{
    object.fetchInBackground(new GetCallback<ParseObject>() 
    {
      public void done(ParseObject object, ParseException e) 
      {
        if (e == null) 
        {
          // Success!
        } 
        else 
        {
          // Failure!
        }
      }
    });
}
```

{% endtab %}

{% tab title="Swift" %}

{% endtab %}
{% endtabs %}


# Delete Object

No needs anymore for an Object? Just delete it already!

## Simple way

{% tabs %}
{% tab title="Java" %}

```java
import com.parse.ParseObject;

public void deleteObject(ParseObject object)
{
    object.deleteInBackground();
}
```

{% endtab %}

{% tab title="Swift" %}

{% endtab %}
{% endtabs %}

## With Callback

{% tabs %}
{% tab title="Java" %}

```java
import com.parse.ParseObject;
import com.parse.DeleteCallback;
import com.parse.ParseException;


public void deleteObject(ParseObject object)
{
    object.deleteInBackground(new DeleteCallback() 
    {
        @Override
        public void done(ParseException e)
        {
            
        }
    });
}
```

{% endtab %}

{% tab title="Swift" %}

{% endtab %}
{% endtabs %}


# User Management

At the core of many apps, there is a notion of user account management that lets users access their information in a secure manner. A specialized user class called `ParseUser` is available to automatically handles these kind of functionalities.

`ParseUser` is a subclass of the `ParseObject`, and has all the same features. All the methods that are on `ParseObject` also exist in `ParseUser`. The difference is that `ParseUser` has some special additions specific to user accounts.

## Signing Up&#x20;

{% tabs %}
{% tab title="Java" %}

```java
import com.parse.ParseException;
import com.parse.ParseUser;
import com.parse.SignUpCallback;

public void signUpUser(String username, String password, String email)
{
    ParseUser user = new ParseUser();
    
    user.setUsername(username);
    user.setPassword(password);
    user.setEmail(email);
    
    // other fields can be set just like with ParseObject
    user.put("phone", "650-253-0000");

    user.signUpInBackground(new SignUpCallback() 
    {
      public void done(ParseException e) 
      {
        if (e == null) 
        {
          // Hooray! Let them use the app now.
        } 
        else
        {
          // Sign up didn't succeed. Look at the ParseException
          // to figure out what went wrong
        }
      }
  });
  
}
```

{% endtab %}

{% tab title="Swift" %}

```swift
import Parse
​
class testVC: UIViewController
{
    func SignUpUser(email:String, pwd:String)
    {
        let user = PFUser.init()
        user.username = "demo@symbyoz.io"
        user.email = "demo@symbyoz.io"
        user.password = "demo"
        
        user.signUpInBackground
        {
            (isConnect, error) in
            
            if let error = error
            {
                print (error.localizedDescription)
            }
            else
            {
                if isConnect
                {
                    print ("user connect")
                }
            }  
        }
    }
}

```

{% endtab %}
{% endtabs %}

## Logging In

{% tabs %}
{% tab title="Java" %}

```java
import com.parse.LogInCallback;
import com.parse.ParseException;
import com.parse.ParseUser;

public void logInUser(String username, String password)
{
    ParseUser.logInInBackground(username, password, new LogInCallback() 
    {
      public void done(ParseUser user, ParseException e)
      {
        if (user != null) 
        {
            // Hooray! The user is logged in.
        } 
        else 
        {
            // Signup failed. Look at the ParseException to see what happened.
        }
      }
    });
}
```

{% endtab %}

{% tab title="Swift" %}

```swift
import Parse
​
class testVC: UIViewController
{
    ​
   func connectUser(email: String, password: String, completion:@escaping (_ isSuccess: Bool, _ error: String) -> Void)
    {
        PFUser.logInWithUsername (inBackground:email, password: password, block:
        {
            (User, error) -> Void in
                
            if ((error) != nil)
            {
                completion(false, error!.localizedDescription)
            }
            else
            {
                if let user = User
                {
                    print ("user = ", user.description)
                    completion(true, "User connected")
                }
                else
                {
                    completion(false, "User is empty")
                }
            }
        })
    }

}
```

{% endtab %}
{% endtabs %}

## Get current User

{% tabs %}
{% tab title="Java" %}

```java
import com.parse.ParseUser;

public void getUser()
{
    ParseUser currentUser = ParseUser.getCurrentUser();
    
    if (currentUser != null) 
    {
        // do stuff with the user
    } 
    else 
    {
        // show the signup or login screen
    }
}
```

{% endtab %}

{% tab title="Swift" %}

```swift
import Parse

class testVC: UIViewController
{
    func getUser ()
    {
        let currentUser = PFUser.currentUser
    
        if currentUser != nil 
        {
            if currentUser!.isNew 
            {
                print ("is new user")
            }
        }
    }
}



```

{% endtab %}
{% endtabs %}


# Queries

As we've already seen in the "[**Get Object**](/code_examples/get-object)" section of this doc, `Query` with the `getInBackground` method allow you to retrieve an `Object` from your database. But there is many other ways to retrieve specific data that you want without getting only one result or an array of results that you don't need.

Here we are going to see how to use the most of your `Query` functions to get the best result out of it.


# Subclasses

Subclassing is completely optional, however it has many advantages, including terseness, extensibility, and support for autocomplete. In Symbyoz you can **automatically** generate subclasses of your Modules, in `Swift` and `Java` , from the **Configuration** section of your backend.

It will literally transforms this code:

{% tabs %}
{% tab title="Java" %}

```java
ParseObject object = new ParseObject("ClassName");
object.put("displayName", "John Doe");
object.put("isFunny", false);
object.put("age", 50);
```

{% endtab %}

{% tab title="Swift" %}

```swift
var object = PFObject(className:"ClassName")
object["displayName"] = "John Doe"
object["isFunny"] = false
object["age"] = 50
```

{% endtab %}
{% endtabs %}

Into this:

{% tabs %}
{% tab title="Java" %}

```java
ClassName object = new ClassName();
object.setDisplayName("John Doe");
object.setIsFunny(false);
object.setAge(50);
```

{% endtab %}

{% tab title="Swift" %}

```swift
var object = ClassName()
object.displayName = "John Doe"
object.isFunny = false
object.age = 50
```

{% endtab %}
{% endtabs %}

## Creating Subclass

Follow this example to have your own subclass ready to use.

1. Create your class as following

{% tabs %}
{% tab title="Java" %}
{% code title="ClassName.java" %}

```java
import com.parse.ParseClassName;
import com.parse.ParseObject;

@ParseClassName("ClassName")
public class ClassName extends ParseObject
{
  public String getDisplayName() 
  {
    return getString("displayName");
  }
  
  public void setDisplayName(String value) 
  {
    put("displayName", value);
  }
}
```

{% endcode %}
{% endtab %}

{% tab title="Swift" %}

```swift
import Foundation
import Parse

class Address: PFObject, PFSubclassing
{
    @NSManaged var media:  PFFile?
    @NSManaged var fullAddress:  String?
    @NSManaged var street:  String?
    @NSManaged var googlePlaceId:  String?
    @NSManaged var city:  String?
    @NSManaged var streetNumber:  String?
    @NSManaged var isDeleted:  Bool
    @NSManaged var owner:  PFUser?
    @NSManaged var location:  PFGeoPoint?
    @NSManaged var country:  String?
    @NSManaged var postalCode:  String?
    @NSManaged var comment:  String?
    @NSManaged var isBillingAddress:  Bool
        
    override init()
    {
        Address.registerSubclass()
        super.init()
    }
    
    static func parseClassName() -> String
    {
        return "Address"
    }
}
```

{% endtab %}
{% endtabs %}

2\. Register your class before you initialize Parse in your `Application` class

{% tabs %}
{% tab title="Java" %}
{% code title="MyApp.java" %}

```java
import com.parse.Parse;
import android.app.Application;

public class MyApp extends Application 
{
  @Override
  public void onCreate() 
  {
    super.onCreate();
    
    // REGISTER SUBCLASSES HERE
    ParseObject.registerSubclass(ClassName.class);
    
    // Initialize Parse SDK (more info at "Connect to Android App")
    Parse.initialize(new Parse.Configuration.Builder(this)
      .applicationId("YOUR_APP_ID")
      .clientKey("YOUR_CLIENT_KEY")
      .server("https://xxxx.parse-symbyoz.com/parse/")
      .enableLocalDataStore()
      .build()); 
  }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

And you're all done!&#x20;

Now you can simply use it as you would use any other `Object` but with a structured model and accessor added.


# Cloud Code

Listing of Cloud Code functions inside Symbyoz engine

## Stripe

```javascript
/**
 * @param  {boolean} liveMode
 * @return Stripe
 */
 
function getStripe(liveMode)
{
    if (liveMode == false && process.env.STRIPE_DEV_KEY !== null) {
        console.log('import Stripe with key : '+process.env.STRIPE_DEV_KEY);
        return require("cloud/node_modules/stripe/lib/stripe.js")(process.env.STRIPE_DEV_KEY);
    } else {
        console.log('import Stripe with key : '+process.env.STRIPE_KEY);
        return require("cloud/node_modules/stripe/lib/stripe.js")(process.env.STRIPE_KEY);
    }
}

/**
 * Create Stripe Charge with customer
 */
 
Parse.Cloud.define("StripeChargeWithCustomer", function(rq, response){
    var user = rq.user;
    if (!user) {
        return response.error('User must be logged');
    }

    var params = rq.params;
    if (!params.amount || !params.currency || !params.customer || !params.description) {
        return response.error("Missing parameters: need amount, currency, customer and description");
    }
    if (!params.livemode) {
        var livemode = false;
    } else {
        var livemode = params.livemode;
    }

    getStripe(livemode).charges.create({
        amount: params.amount,
        currency: params.currency,
        customer: params.customer,
        description: params.description
    }, function(err, charge) {
        if(err) {
            return response.error(err.statusCode, err.raw);
        }

        if (charge.status == 'failed') {
            return response.error('KO');
        } else {
            return response.success('OK');
        }
    });
});

/**
 * Create Stripe Charge with source
 */
Parse.Cloud.define("StripeChargeWithSource", function(rq, response){
    var user = rq.user;
    if (!user) {
        return response.error('User must be logged');
    }

    var params = rq.params;
    if (!params.amount || !params.currency || !params.source || !params.description) {
        return response.error("Missing parameters: need amount, currency, source and description");
    }
    if (!params.livemode) {
        var livemode = false;
    } else {
        var livemode = params.livemode;
    }

    getStripe(livemode).charges.create({
        amount: params.amount,
        currency: params.currency,
        source: params.source,
        description: params.description
    }, function(err, charge) {
        if(err) {
            return response.error(err.statusCode, err.raw);
        }

        if (charge.status == 'failed') {
            return response.error('KO');
        } else {
            return response.success('OK');
        }
    });
});

/**
 * Create Stripe Customer
 */
Parse.Cloud.define("StripeCustomerCreate", function(rq, response){
    var user = rq.user;
    if (!user) {
        return response.error('User must be logged');
    }

    var params = rq.params;
    if (!params.email || !params.source) {
        return response.error("Missing parameters: need email, source");
    }
    if (!params.livemode) {
        var livemode = false;
    } else {
        var livemode = params.livemode;
    }

    getStripe(livemode).customers.create({
        email: params.email,
        source: params.source,
    }, function(err, customer) {
        if(err) {
            return response.error(err.statusCode, err.raw);
        }
        return response.success(customer.id);
    });
});

```

## &#x20;SMS by AWS SNS

```javascript
/**
 * Send SMS with AWS SNS
 */
Parse.Cloud.define("sendAWSSMS", function(rq, response){
    var AWS = require('cloud/node_modules/aws-sdk/index.js');

    AWS.config.update({
        accessKeyId: process.env.SNS_ACCESS_KEY,
        secretAccessKey: process.env.SNS_SECRET_KEY,
        region: process.env.SNS_REGION
    });

    var phone = rq.params.phone;
    if (!phone) {
        return response.error('phone parameter is missing');
    }
    var message = rq.params.message;
    if (!message) {
        return response.error('message parameter is missing');
    }

    var sns = new AWS.SNS();

    sns.setSMSAttributes({
        attributes: {
            DefaultSenderID: process.env.APP_NAME
        }
    }, function(error, data){
        if (error) {
            return response.error("error when defining sms preferences", error);
        }

        sns.publish({
            Message: message,
            PhoneNumber: phone,
        }, function(error, data) {
            if (error) {
                return response.error(error.statusCode, error.message);
            }

            console.log(data);
            return response.success('Sending success');
        });
    });
});

```

## SMS by SMSPartner

```javascript
/**
 * Send SMS with SMS Partner
 */
Parse.Cloud.define("sendSMSPartner", function(rq, response) {
    var request = require('cloud/node_modules/request/index.js');
    var phone = rq.params.phone;
    if (!phone) {
        return response.error('phone parameter is missing');
    }
    var message = rq.params.message;
    if (!message) {
        return response.error('message parameter is missing');
    }

    var requestData = {
        apiKey: process.env.SMSPARTNER_KEY,
        phoneNumbers: phone,
        sender: process.env.APP_NAME,
        message: message
    }

    request.post(
        'https://api.smspartner.fr/v1/send',
        { json: requestData },
        function (error, res, body) {
            if (!error && res.statusCode == 200) {
                return response.success(body);
            } else {
                return response.error(body);
            }
        }
    );
});
```

## Push-Notification to Channel

```javascript
/**
 * Send Push to channels
 */
 
Parse.Cloud.define("sendPushTo", function(rq, response){
    var user = rq.user;
    if (!user) {
        return response.error('User must be logged');
    }
    var channels = rq.params.channels;
    if (!channels) {
        return response.error('channels parameter is missing');
    } else if (typeof(channels) != 'object') {
        channels = [channels];
    }
    var message = rq.params.message;
    if (!message) {
        return response.error('message parameter is missing');
    }
    var options = rq.params.options;
    if (!options) {
        options = {};
    }

    var data = {
        alert: message,
        badge: "Increment",
        sound: "soundNotifUserContact.caf",
        title: process.env.APP_NAME
    };

    for (var attr in options) {
        data[attr] = options[attr];
    }

    Parse.Push.send(
        {
            channels: channels,
            data: data
        },
        {
            useMasterKey: true,
            success: function() {
                return response.success('OK');
            },
            error: function(error) {
                return response.error(error);
            }
        }
    );
});

```

## Send Email with MailGun

```javascript
Parse.Cloud.define("sendEmail", function(rq, response){
    var user = rq.user;
    if (!user) {
        return response.error('User must be logged');
    }

    var templateId = rq.params.templateId;
    if (!templateId) {
        return response.error('templateId parameter is missing');
    }

    var emails = rq.params.emails;
    var users = rq.params.users;
    if (!emails && !users) {
        return response.error('users or emails parameter is required');
    }

    var json = {
        'users': users,
        'emails': emails
    };
    var request = require('request');
    var url = process.env.SYMBYOZ_URL+'/cloud/send-email/'+templateId;
    console.log('Call URL '+url);
    console.log('With header x-parse-session-token:'+rq.headers['x-parse-session-token']);
    request({
        url: url,
        method: 'POST',
        json: json,
        headers: {
            'x-parse-session-token': rq.headers['x-parse-session-token']
        }
    }, function (error, resp, body) {
        if (!resp) {
            console.log('Unable to connect to '+url);
            return response.error(500, 'Unable to connect to Symbyoz');
        }
        if (resp.statusCode != 200) {
            if (body.error) {
                return response.error(resp.statusCode, body.error.message);
            } else {
                return response.error(resp.statusCode, body);
            }
        }
        console.log(body);
        return response.success('OK');
    });

});
```


