Appsco Market will notify you on the notification URL registered in the Market Item when an order is processed and when subscription status changes.
These are the notification kinds Market can send
order_processed
- Sent when an order is successfully processed. On this notification kind you would usually want to prepare your application's environment/state to accomodate this new order - for example initialize new user account or create new application instance.subscription_canceled
- Sent when subscription for existing application is canceledsubscription_charged_successfully
- Sent when subscription has been charged for one billing periodsubscription_charged_unsuccessfully
- Sent when subscription renewal was not being possible to be chargedsubscription_expired
- Sent when subscription expiressubscription_trial_ended
- Sent when subscription trial period ends, only if subscription has the trial periodsubscription_went_active
- This will only be sent after the subscription’s first authorized transaction, or when transitioning from a past due status. Subscriptions with trial periods will never trigger this notification. Subscriptions moving out of pending (future billing date has now been reached) will always trigger this, even if the transaction is not authorized.subscription_went_past_due
- Sent when subscription was not being renewed successfully after the due period
They are defined in the Appsco\Market\Api\Model\Notification::KIND_*
constants
Appsco Market Notifications are JWT based. It's
issuer is appsco-market
- the Client ID of the Appsco Market registered on Appsco Accounts. Notifications are
signed with RS256 algorithm and to validate it you should obtain Market certificate using the
Appsco Accounts certificateGet
API method.
Appsco Market Notification defines following custom claims:
kind
- The notification kindorder_id
- The ID of the order notification is about - defined by you if you initiated the order by custom order request, otherwise generated by Appsco Marketapp_id
- The ID of the Appsco Market application the notification is about. You should store this app id for new instances in order to be able to reconfigure thempackage_id
- The ID of the Appsco Market Package the application is purchased byowner_id
- Appsco Accounts ID of the application ownerchallenge
- Challenge you have to reply to in order to validate your callback URL
In order to properly validate Market Notification, couple of things should be done:
- decode JWT token
- check if Issuer claim matches Appsco Market's Client ID - "appsco-market"
- check the Issued At claim if token has expired
- check the JWT signature with Market certificate
- check if Jwt ID has already been processed
Appsco Market API Bundle appsco_market_api.notification.validator
service does all these validations expect the last
one - Jwt ID validation. For details check the Jwt ID validation document.
To all Market notifications you have to response with HTTP status code 200 and empty response, except for the challenge notification when you have to respond with challenge response.
Use MarketClient method
/**
* @param string $jwtToken
* @return \BWC\Component\Jwe\Jose
*/
public function receiveNotification($jwtToken)
to get the Notification data model object from the passed JTW token.
Use notification validator service method
/**
* @param Notification $notification
* @throws InvalidNotificationException
* @return void
*/
public function validate(Notification $notification);
to validate the received notification
- issuer validity
- expiry
- signature
Example
use Symfony\Component\HttpFoundation\Request;
class DefaultController extends \Symfony\Bundle\FrameworkBundle\Controller\Controller
{
public function callbackAction(Request $request)
{
$jwtToken = $request->request->get('jwt');
$notification = $this->get('appsco_market_api.client')->receiveNotification($jwtToken);
$this->get('appsco_market_api.notification.validator')->validate($notification);
$this->jtiValidation($notification); // check if jti is repeated
$this->processNotification($notification); // process the notification
return new Response('');
}
}
When you register you Market Item callback URL it has to be validated by replying to a challenge token.
use Symfony\Component\HttpFoundation\Request;
class DefaultController extends \Symfony\Bundle\FrameworkBundle\Controller\Controller
{
public function callbackAction(Request $request)
{
$jwtToken = $request->request->get('jwt');
$notification = $this->get('appsco_market_api.client')->receiveNotification($jwtToken);
$this->get('appsco_market_api.notification.validator')->validate($notification);
$this->jtiValidation($notification); // check if jti is repeated
if ($notification->getChallenge()) {
// challenge notification - have to respond with challenge response
return new Response($this->get('appsco_market_api.client')->notificationChallengeReply($notification));
} else {
// notification about an order/subscription
$this->processNotification($notification); // process the notification
return new Response('');
}
}
}