App Center Integration – Asynchronous Events

Asynchronous events

All subscription events that involve a response can also be supported as asynchronous (delayed response) events. (SUBSCRIPTION_NOTICE is the only subscription event that does not involve a response and therefore is only supported as a synchronous event.)

When App Center calls an Partner with a notification URL, they return a JSON or XML response, as well as an HTTP response code. Usually, this code is 200 (OK) or 201 (Created). Additionally, however, App Center will recognize an code of 202 (Accepted) as a mechanism for the Partner to tell App Center that the event has been received and is being processed, and the Partner will notify App Center upon completion. The Partner can make an HTTP POST to the /api/integration/v1/events/{eventUrl}/result endpoint to notify App Center of the result. The POST body is the same as it would be for a synchronous event response. The subscription or assignment will remain in a “pending” state (e.g., PENDING_USER_ACTIVATION, PENDING_REMOTE_CREATION, or PENDING_REMOTE_CANCELLATION) in the App Center marketplace until App Center is notified of the result. When a subscription or assignment is in the pending state, the user cannot act upon it.

Asynchronous event notification flow

All asynchronous event notifications follow the same general flow:

  1. An event is triggered by a customer action (e.g., purchasing an application, upgrading an existing subscription, cancelling a subscription, or failing to pay an invoice).
  2. App Center sends an asynchronous event notification to the application vendor (Partner). This event is uniquely identified by an event URL. More details about the notification URL are provided below.
  3. The Partner must validate the OAuth-signature on the request, then can read the event URL from the parameters to send an HTTP GET request for more information about the particular subscription event.
  4. App Center sends a JSON or XML response to the Partner.
  5. The Partner then does a POST request back to App Center, passing account and/or status information. This status information is used by App Center to provide feedback to the customer via the App Center UI.
  6. The key difference with an asynchronous event is that the header returns a 202 (Accepted) HTTP code. App Center will recognize this code as a pending event.
  7. Once the event is manually resolved (such as an account is provisioned), the Partner can POST a result to the eventUrl.

Example asynchronous event notification flow

An example of a asynchronous event notification flow is shown below using a create subscription.

User Bob purchases application Gizmo123. This creates an asynchronous SUBSCRIPTION_ORDER event identified by URL https://www.sapappcenter.com/api/integration/v1/events/12345.

App Center calls http://example.com/create?url=https%3A%2F%2Fwww.sapappcenter.com%2Fapi%2Fintegration%2Fv1%2Fevents%2F12345
Example.com issues a signed fetch to: https://www.sapappcenter.com/api/integration/v1/events/12345

App Center sends a JSON or XML response to the Partner.

JSON

{
    "type": "SUBSCRIPTION_ORDER",
    "marketplace": {
      "baseUrl": "https://www.sapappcenter.com",
      "partner": "Partner Name"
    },
    "creator": {
      "address": {
        "city": "Cambridge",
        "country": "US",
        "phone": "8582312882",
        "state": "MA",
        "street1": "123 Main St",
        "zip": "02142"
      },
      "email": "testuser@testco.com",
      "firstName": "Test",
      "language": "en",
      "lastName": "User",
      "locale": "en-US",
      "openId": "https://www.sapappcenter.com/openid/id/5d1f6f79-efff-411e-abe5-0b0a01610f04",
      "uuid": "5d1f6f79-efff-411e-abe6-0b0a01610f04"
    },
    "payload": {
      "company": {
        "country": "US",
        "name": "Test User",
        "phoneNumber": "8582312882",
        "uuid": "dc61a736-55b6-40fc-9b5a-6b17cbe6eb62"
      },
      "order": {
        "editionCode": "0D5C06DB-FFEC-43a1-A6AF-EFB7E9B17905",
        "pricingDuration": "MONTHLY",
        "items": [{
          "quantity": "3",
          "unit": "USER"
        }]
      }
    }
}

XML

<?xml version="1.0" encoding="UTF-8" ?>
<event>
        <type>SUBSCRIPTION_ORDER</type>
        <marketplace>
                <baseUrl>https://www.sapappcenter.com</baseUrl>
                <partner>Partner Name</partner>
        </marketplace>
        <creator>
                <address>
                        <city>Cambridge</city>
                        <country>US</country>
                        <phone>8582312882</phone>
                        <state>MA</state>
                        <street1>123 Main St</street1>
                        <zip>02142</zip>
                </address>
                <email>testuser@testco.com</email>
                <firstName>Test</firstName>
                <language>en</language>
                <lastName>User</lastName>
                <locale>en-US</locale>
                <openId>https://www.sapappcenter.com/openid/id/5d1f6f79-efff-411e-abe5-0b0a01610f04</openId>
                <uuid>5d1f6f79-efff-411e-abe6-0b0a01610f04</uuid>
        </creator>
        <payload>
                <company>
                        <country>US</country>
                        <name>Test User</name>
                        <phoneNumber>8582312882</phoneNumber>
                        <uuid>dc61a736-55b6-40fc-9b5a-6b17cbe6eb62</uuid>
                </company>
                <order>
                        <editionCode>0D5C06DB-FFEC-43a1-A6AF-EFB7E9B17905</editionCode>
                        <pricingDuration>MONTHLY</pricingDuration>
                        <items>
                                <quantity>3</quantity>
                                <unit>USER</unit>
                        </items>
                </order>
        </payload>
</event>

Example.com starts the creation a new account for Bob in its account system.

Example.com returns a JSON or XML response to the original HTTP request.

JSON

Status Code: 202 Accepted
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Length: 17
Content-Type: application/json;charset=UTF-8
Date: Tue, 25 Aug 2015 20:40:25 GMT
Expires: 0
Pragma: no-cache
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=E93047B4DE01A6D3447EACEDD462CA8A; Path=/; HttpOnly
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
x-content-type-options: nosniff
{
    "success":true
}

XML

Status Code: 202 Accepted
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Length: 35
Content-Type: application/xml;charset=UTF-8
Date: Tue, 25 Aug 2015 20:40:25 GMT
Expires: 0
Pragma: no-cache
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=E93047B4DE01A6D3447EACEDD462CA8A; Path=/; HttpOnly
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
x-content-type-options: nosniff
<result>
    <success>true</success>
</result>

App Center puts the subscription into the PENDING_REMOTE_CREATION state. The user cannot do anything with the subscription at this time.

The Partner sends an HTTP POST to https://www.sapappcenter.com/api/integration/v1/events/12345/result to indicate the account creation is complete. Note that the POST body is the same object as a synchronous event response.

JSON

Status Code: 200 OK
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Length: 28
Content-Type: application/json;charset=UTF-8
Date: Tue, 25 Aug 2015 20:40:25 GMT
Expires: 0
Pragma: no-cache
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=E93047B4DE01A6D3447EACEDD462CA8A; Path=/; HttpOnly
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
x-content-type-options: nosniff
{
    "accountIdentifier":"789xyz",
    "success":true
}

XML

Status Code: 200 OK
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Length: 47
Content-Type: application/xml;charset=UTF-8
Date: Tue, 25 Aug 2015 20:40:25 GMT
Expires: 0
Pragma: no-cache
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=E93047B4DE01A6D3447EACEDD462CA8A; Path=/; HttpOnly
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
x-content-type-options: nosniff
<result>
    <accountIdentifier>789xyz</success>
    <success>true</success>
</result>

Or in the event of an error, Example.com can return an error code.

JSON

Status Code: 409 Conflict
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Length: 46
Content-Type: application/json;charset=UTF-8
Date: Tue, 25 Aug 2015 20:40:25 GMT
Expires: 0
Pragma: no-cache
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=E93047B4DE01A6D3447EACEDD462CA8A; Path=/; HttpOnly
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
x-content-type-options: nosniff
{
    "success": "false"
    "errorCode": "USER_ALREADY_EXISTS"
    "message": "Optional message about the user already existing on Partner"
}

XML

Status Code: 409 Conflict
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Length: 62
Content-Type: application/xml;charset=UTF-8
Date: Tue, 25 Aug 2015 20:40:25 GMT
Expires: 0
Pragma: no-cache
Server: Apache-Coyote/1.1
Set-Cookie: JSESSIONID=E93047B4DE01A6D3447EACEDD462CA8A; Path=/; HttpOnly
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
x-content-type-options: nosniff
<result>
    <success>false</success>
    <errorCode>USER_ALREADY_EXISTS</errorCode>
    <message>Optional message about the user already existing on Partner</message>
</result>

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>