Refunding a Purchase

Hopefully our users will never second guess their decision to buy the Magnificent Moons package. But in the event that they have buyer’s remorse, we should offer them a means to return their purchase for a refund.

To do that, we’ll add a new intent through which a user can ask for a refund. In the interaction model, the intent is defined like this:

 { "name": "RefundIntent", "samples": [ "refund the {productName} pack", "return the {productName} package", "return the {productName} extension" ], "slots": [ { "name": "productName", "type": "ADDON_PRODUCTS" } ] },

As defined here, when the user wants a refund, they can say, “refund the Magnificent Moons pack,” “return the Magnificent Moons package,” or “return the Magnificent Moons extension.” Just as with BuyIntent, the “productName” slot is used here to allow flexibility in what products this intent works with, should we decide to offer more products later.

Now we need a request handler for this new intent. Here’s a handler implementation that should do the job:

 const​ RefundIntentHandler = {
  canHandle(handlerInput) {
 const​ requestEnvelope = handlerInput.requestEnvelope;
 return​ Alexa.getRequestType(requestEnvelope) === ​'IntentRequest'
  && Alexa.getIntentName(requestEnvelope) === ​'RefundIntent'​;
  },
 async​ handle(handlerInput) {
 const​ slot = Alexa.getSlot(handlerInput.requestEnvelope, ​'productName'​);
 const​ referenceName =
  slot.resolutions.resolutionsPerAuthority[0].values[0].value.id;
 const​ productId =
  (​await​ ProductUtils.getProduct(handlerInput, referenceName))
  .productId;
 
 return​ handlerInput.responseBuilder
  .addDirective({
  type: ​"Connections.SendRequest"​,
  name: ​"Cancel"​,
  payload: {
  InSkillProduct: {
  productId: productId
  }
  },
  token: ​"correlationToken"
  })
  .getResponse();
  }
 };

You might be feeling a bit of deja vu looking at the implementation of RefundIntentHandler. Indeed, it looks an awful lot like how we implemented BuyIntentHandler. Aside from the fact that it checks for an intent name of RefundIntent in the canHandle() function (instead of BuyIntent), the only difference is the value of the name property in the Connections.SendRequest directive. Since this is a refund, we set name to “Cancel” instead of “Buy”.

Finally, we need to handle the response request. Just like the other times we’ve sent a Connections.SendRequest directive for buying and upselling, Alexa will send us a Connections.Response request as a callback after handling the refund. If we do nothing, our existing ContinueAfterPurchaseHandler handler will handle the request and thank the user for their purchase—which is a little weird considering that they just asked for a refund.

So, let’s write a new handler specific to a refund callback request. As it turns out the name property we send in the Connections.SendRequest directive is sent back in the Connections.Response request. So we can write a canHandle() function in our handler that checks to see if the incoming request’s name property is equal to “Cancel”. If so, we know that the request follows a refund directive.

In the case of a refund, the handler can return anything you want to be spoken, but should end the session. The following request handler does that:

 const​ ContinueAfterRefundHandler = {
  canHandle(handlerInput) {
 const​ requestEnvelope = handlerInput.requestEnvelope;
 return​ Alexa.getRequestType(requestEnvelope) === ​'Connections.Response'
  && requestEnvelope.request.payload.purchaseResult === ​'ACCEPTED'
  && requestEnvelope.request.name === ​'Cancel'​;
  },
  handle(handlerInput) {
 return​ StandardHandlers.CancelAndStopIntentHandler.handle(handlerInput);
  }
 };

Notice that the canHandle() function checks that the request’s name property is “Cancel”, and additionally that the request type is Connections.Response and the purchase result is “ACCEPTED”. If so, then the handle() function simply hands off the handlerInput object to the handle() function of the CancelAndStopIntentHandler request handler, telling the user goodbye and ending the session.

For both of these new request handlers, don’t forget to export them from the module:

  ...
 module.exports = {
  BuyIntentHandler: BuyIntentHandler,
» ContinueAfterRefundHandler: ContinueAfterRefundHandler,
» RefundIntentHandler: RefundIntentHandler,
  ContinueAfterPurchaseHandler: ContinueAfterPurchaseHandler
 };

And then be sure to register them with the skill builder:

 exports.handler = Alexa.SkillBuilders.custom()
  .addRequestHandlers(
  ...
» PurchaseIntentHandlers.RefundIntentHandler,
» PurchaseIntentHandlers.ContinueAfterRefundHandler,
  ...
  )

After deploying these changes, you should be able to request a refund for the Magnificent Moons package. The flow will look something like this:

images/sell/refund.png

 

Notice that the refund isn’t handled directly in the flow of the skill. Instead, a card is sent to the user and they are instructed to contact Amazon customer service for the refund. The card, as it appears in the companion application, looks like this:

images/sell/refundcard.png

 

Finally, after the card is sent, the session ends and Alexa says “Goodbye” when the handler for the Connections.Response request forwards the handlerInput to the CancelAndStopIntentHandler.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset