WebAPI/WebPayment: Difference between revisions

From MozillaWiki
Jump to navigation Jump to search
(→‎In-app payment: fixed camel case of productData in legend)
Line 117: Line 117:
*** '''name''' (mandatory): A short description of the product.
*** '''name''' (mandatory): A short description of the product.
*** '''description''' (mandatory): A long description of the product.
*** '''description''' (mandatory): A long description of the product.
*** '''productdata''': A freeform string, no longer than 255 characters. This can be anything the app might need to identify the product with when a postback is sent back to the app.
*** '''productData''': A freeform string, no longer than 255 characters. This can be anything the app might need to identify the product with when a postback is sent back to the app.
*** '''postbackURL''': URL where the payment processor sends an HTTP POST message to whenever a purchase completes. The application server needs to acknowledge these POST messages, or else the transactions will be canceled. If the payment processor stores a different postback URL, this one should override the stored one. This way, application developer could choose different endpoints for different kind of digital goods.
*** '''postbackURL''': URL where the payment processor sends an HTTP POST message to whenever a purchase completes. The application server needs to acknowledge these POST messages, or else the transactions will be canceled. If the payment processor stores a different postback URL, this one should override the stored one. This way, application developer could choose different endpoints for different kind of digital goods.
*** '''chargebackURL''': URL where the payment processor sends an HTTP POST message to whenever a refund associated with this transaction is done. If the payment processor stores a different chargeback URL for this application, the one within the JWT should override the stored one.
*** '''chargebackURL''': URL where the payment processor sends an HTTP POST message to whenever a refund associated with this transaction is done. If the payment processor stores a different chargeback URL for this application, the one within the JWT should override the stored one.

Revision as of 20:14, 12 December 2012

WebPayment API Specification (DRAFT)

Goal

The goal of this API is to allow Open Web Apps to initiative a payment (or a refund) form the user for a virtual good.

Status

See bug 767818 for the 'navigator.mozPay' implementation.

Currently only implemented for B2G.

Proposed API

Expose the pay function to the navigator object

interface nsIDOMNavigatorPayment
{
  DOMRequest mozPay(in jsval jwts);
}

Proposers

Andreas Gal and Fernando Jiménez. Based on Mike Hanson's and Kumar McMillan's work for the Marketplace in-app payments solution

WebPayments Architecture (DRAFT)

Introduction

The goal of this Web Payments architecture is to allow Open Web Apps to initiate a payment (or a refund) from the user for a virtual good via the navigator.mozPay function.

An OWA should be able to access the in-app web payments services using an API (navigator.mozPay) exposed by the User Agent on the device (for the B2G use case). The UA must use an asynchronous message loop to convey billing requests and responses between the application and the Payment Processor (or Provider). In practice, the applications should never directly communicate with the Payment Processors's servers. Instead, the application should send billing requests to the UA via 'navigator.mozPay()' and should receive purchase responses from the UA in the form of asynchronous callbacks.

Payment flow overview

  • The app initiates a payment by signing a JWT request and calling navigator.mozPay().
  • This starts the buyflow in a content iframe inside a trusted dialog ("chrome dialog").
  • A purchasing flow is served from the Payment Provider's server as an HTML5 document inside the trusted dialog.
  • The buyer is authenticated by the Payment Provider (via the network (radio), BrowserID assertion or whatever authentication mechanisms the Payment Provider chooses).
  • The buyer completes or cancels the purchase. (Note that the Payment Provider might also require an authorization step).
  • The app receives a Javascript callback when the buyer accepts or cancels the purchase.
  • The app serser receives a signed POST request with a Payment Provider transaction identifier indicating that the purchase was completed successfully.

Detailed payment flow

This detailed payment flow is based on the proposal for supporting Telefónica's Carrier Billing functionality in B2G, but it could be extended to any other Payment Provider.

Entities

Application
Open Web App which offers digital goods to be sold. OWAs that charge users via navigator.mozPay() require a client and server side.
BlueVia portal
BlueVia is Telefónica's developer program. Developers can register in BlueVia portal in order to make use of TEF Carrier APIs, such as the payment API. We will be using Telefónica's Payment Provider as an example for the payment flow explanation and BlueVia is part of it.
Developer
Application developer, seller of digital goods.
Mozilla Marketplace
Developer portal and application repository. Developers can submit apps to the Mozilla Marketplace so the users can purchase and download this apps. The Mozilla Marketplace would also be using the navigator.mozPay function to charge users for application purchases.
Payment Provider (or Processor)
Offers merchants online services for accepting electronic payments by a variety of payment methods (credict card (CC), direct to bill (D2B), etc.).
Telefónica ID (pending branding)
Telefónica's End user/Customer portal. This customers will be the ones charged for application downloads or in-app purchases.
User
End user who wants to make a purchase for a digital good.
User Agent
B2G

User sign-up and sign-in

In order to allow billing charges when the user can't be identified via the MSISDN transmitted over the network, the user should be registered and logged in Telefónica ID (Telefónica's customers portal).

Currently, there is not a final decision about the authentication mechanisms chosen for B2G v1.

User sign-up and sign-in in Telefónica ID Connect is beyond the scope of this document.

Developer registration

In order to submit applications that makes use of the Telefónica Carrier Billing functionality to the Mozilla Marketplace an app developer should be registered in BlueVia (Telefónica's developers portal).

For v1, B2G applications are going to be purchased via Mozilla Marketplace. So application developers that requires BlueVia in-app billing functionality should also be registeredd in BlueVia as part of his Mozilla Marketplace registration.

A privileged developer registration API is exposed by BlueVia.

Application registration

In order to provide in-app billing functionality an application should be registered in BlueVia This is a similar case as developer registration. Open Web Apps that requires BlueVia in-app billing capabilities should be registered via Mozilla Marketplace (or potentialy other supported marketplace) and also automatically be registered in BlueVia.

An Application Key and Application Secret (generated by BlueVia) should be assigned and provided to the application developer. The application developer can provide BlueVia (via Mozilla Marketplace app registration) with postback and chargeback URLs (this URLs should be editable via Mozilla Marketplace / BlueVia portal).

The application secret will be used by the developer to sign the JWT included with the navigator.mozPay() function. The developer must save the application key and application secret securely in his app server. He must generate the signed JWT using server-side code.

A privileged app registration/edition API is exposed by BlueVia.

Application registration

In-app payment

  • The user installs a previously registered application via Mozilla Marketplace.
  • As his daily use the user decides to purchase a digital good offered by the application.
  • The app generates a payment request that contains all the information about the item being purchased: price, currency, name, description, and so on. The app signs the payment request with its app secret and encodes the whole thing as a JSON Web Token (JWT). The developer must generate the signed JWT using server-side code. The Mozilla Marketplace might expose a JWT generation tool based on the payment information provided by the developer and the supported payment methods that the developer should have previously set up. (TBD). In any case, there are several libraries (like PyJWT, ruby-jwt, node-jwt-simple, PHP luciferous/jwt, Java jsontoken and JSON.NET) to help encoding and decoding JWT.

Example of server-side JWT generation:

 cakeToken = jwt.encode({
   "iss" : sellerIdentifier,
   "aud" : "tu.com",
   "typ" : "tu.com/payments/v1/pay",
   "exp" : 1337357297,
   "iat" : 1337360897,
   "request" : {
     "name" : "Piece of Cake",
     "description" : "Virtual chocolate cake to fill your virtual tummy",
     "price" : [
     {
       "currency": "USD",
       "amount": "5.50"
     }, 
     {
       "currency": "BRL",
       "amount": "11.07"
     }],
     "defaultPrice": "USD",
     "productData" : "my_product_id=1234&my_session_id=XYZ",
     "postbackURL" : "http://developersserver.com/postback",
     "chargebackURL" : "http://developerserver.com/chargeback"
   }
 }, APP_SECRET)

Here is a detailed explanation of the in-app payment JWT:

    • iss: The issuer of the JWT. This is the application key assigned during the app registration process for this specific payment provider (BlueVia).
    • typ (mandatory): The JWT type (identifies the payment provider, BlueVia, and the JWT version that must be supported by the provider).
    • iat: Issued at time. This is a UTC Unix timestamp of when the JWT was issued.
    • exp: Expiration. A UTC Unix timestamp of when the JWT should expire.
    • request (mandatory): Request object.
      • price (mandatory): List of prices per currency.
        • currency: Currency code expressed following the recommendations from ISO 4217.
        • amount: Value withouth taxes of the digital good being sold.
      • defaultPrice: This is the currency code for the default price to be considered as payment price when there is not matching between the customer currency and the currency prices located in the price collection. This must match with one of the currency codes in the price list.
      • name (mandatory): A short description of the product.
      • description (mandatory): A long description of the product.
      • productData: A freeform string, no longer than 255 characters. This can be anything the app might need to identify the product with when a postback is sent back to the app.
      • postbackURL: URL where the payment processor sends an HTTP POST message to whenever a purchase completes. The application server needs to acknowledge these POST messages, or else the transactions will be canceled. If the payment processor stores a different postback URL, this one should override the stored one. This way, application developer could choose different endpoints for different kind of digital goods.
      • chargebackURL: URL where the payment processor sends an HTTP POST message to whenever a refund associated with this transaction is done. If the payment processor stores a different chargeback URL for this application, the one within the JWT should override the stored one.
  • For a user to make a purchase, the app must execute the Javascript method navigator.mozPay() with this signed payment request. For example, the app might have a 'buy' button that triggers this method when clicked. Then navigator.mozPay method should take the signed payment JWT or an array of them. As a result of this call a DOMRequest object would be returned. The developer may use this DOMRequest object to monitor the progress of the operation.

let request = navigator.mozPay([signedJWT1, signedJWTn]);
request.onsuccess = function () {
  [...]
}
request.onerror = function () {
  [...]
}

  • The navigator.mozPay method must open a payment request confirmation screen based on the received JWTs, so the user can confirm and choose the payment method that is more appropriate for him. B2G would only show the payment providers for the JWT typ values that are pre-registered in the UA. JWTs containing a typ value not registered in the UA would be considered as invalid.
  • Once the user selects a Payment Provider the UA must open a trusted dialog ("chrome" dialog) containing the Payment Provider's buy flow that is registered in the UA for the typ value of the passed JWT (Telefónica ID in case of BlueVia).
  • User authentication can be done via network authentication (MSISDN) or BrowserID assertion. Authorization could also be done with user password or PIN code sent via SMS. The authentication and authorization mechanisms are reponsibility of the Payment Provider and it is beyond the scope of this document.
  • The purchase is presented to the user for confirmation, with name, description and identifying information from Telefónica ID about the seller.
  • The user confirms the purchase or cancels it.
  • If the user cancels or something goes wrong with the payment process, the flow returns to the DOMRequest.onerror callback.
  • If the user confirms, the Payment Provider should send a POST confirmation message (a JWT) to the postback URL of the seller provided within the JWT request. The postback URL is optional, but strongly recommended. The Payment Processor (also via Mozilla Marketplace) could optionally store a default postback URL as part of his application sign-up process. If a different postback URL is provided within the JWT request, this one would override the default one stored as default in the Payment Provider. This confirmation message contains all the payment request fields (for the price case, only the selected value is returned) plus a transaction identifier, and is signed with the seller's application secret. In the following example, the transactionID field is specific to the BlueVia payment provider.

 {
   "iss" : "tu.com",
   "aud" : sellerIdentifier,
   "typ" : "tu.com/payments/v1/pay",
   "exp" : 1337370900,
   "iat" : 1337360900,
   "request" : {
     "name" : "Piece of Cake",
     "description" : "Virtual chocolate cake to fill your virtual tummy",
     "price" : [{
       "currency": "BRL",
       "amount": "11.07"
     }],
     "productData" : "my_product_id=1234&my_session_id=XYZ",
     "postbackURL" : "http://developersserver.com/postback",
     "chargebackURL" : "http://developerserver.com/chargeback"
   },
   "response": {
     "transactionID": 123456123456123456
   }
 }

  • To verify that the purchase is valid, the application server first needs to decode and verify the JWT in the POST. If the purchase is valid, then the application server should record it and respond with a 200 OK that contains the order ID. The transaction should be canceled by the Payment Provider if the server take longer than x seconds to send a 200 OK response.

The JWT format and callbacks above are compatible with Google's in-app payment system, as well as Mozilla's paypal-based in-app payment flow.

Buy flow

Marketplace payment

(This is just a proposal and not the current Marketplace scenario)

The Mozilla Marketplace use navigator.mozPay to execute purchase transactions for apps. The only difference to in-app payments is that the Marketplace use the app as the issuer (recipient of funds), instead of itself.

Once the user starts an application purchase process, the marketplace generates a payment request that contains all the information about the application being purchased: price, currency, name, description and so on, with the addition of the application key that identifies the developer as issuer of the transaction (recipient of funds) and the marketplace postback and chargeback URLs, so the Marketplace could receive notifications about the transaction result or refunds associated with the transaction. The marketplace signs the payment request with the application secret.

 {
   "iss": sellerIdentifier, // developer identifier in this case
   "aud": "tu.com",
   "typ": "tu.com/payments/v1/pay",
   "exp": 1337370900,
   "iat": 1337360900,
   "request": {
     "name": "Demo app",
     "description": "Demo app",
     "price": [
     {
       "currency": "USD",
       "amount": "0.99"
     }, 
     {
       "currency": "BRL",
       "amount": "1.99"
     }],
     "defaultPrice": "USD",
     "postbackURL": "https://marketplace.mozilla.org/postback",
     "chargebackURL": "https://marketplace.mozilla.org/chargeback",
     "productData": "my_product_id=123"
   }
 }

The buy flow is the same as the in-app payments case for the payment processor's side. As mentioned before, the difference to in-app payments requests is that a marketplace request must contain a postback url in order to notify the market about the successful transaction. This postback and chargeback URLs should prevail over the postback url stored for the application key, so notifications should be received by the marketplace instead of the developer. Once the marketplace receives the details of the transaction it should unlock the application installation, and it could optionally notify the developer about it via the registered postback url for the application.

Refunds

Refunds depend on the technical capabilities of the payment provider. If technically feasible, the UA should direct users to a Payment Provider-hosted refund page (trusted dialog launched from the settings area) that lists the most recent purchases and allows to cancel them. Authentication occurs via MSISDN or BrowserId as for payments.

Refunds for in-app purchases

The navigator.mozPay API allows refunds the same way as it allow purchases, so the developer has the choice of exposing a way to request refunds from his application. The difference between a purchase and a refund is within the JWT request parameters. The content of this refund requests depend on the needs of the Payment Provider. For the BlueVia case, a transaction ID, a reason and an optional chargeback URL parameters are required.

 {
    "iss" : sellerIdentifier,
    "aud" : "tu.com",
    "typ" : "tu.com/payments/v1/refund",
    "exp" : 1337370900,
    "iat" : 1337360900,
    "request" : {
      "refund": "123456123456123456", // transaction ID
      "reason": "refund",
      "chargebackURL": "https://developerserver.com/chargeback"
    }
 }

The developer would receive a chargeback notification containing the details of the refund operation.

 {
    "iss" : "tu.com",
    "aud" : sellerIdentifier,
    "typ" : "tu.com/payments/v1/refund",
    "exp" : 1337370900,
    "iat" : 1337360900,
    "request" : {
      "name" : "Piece of Cake",
      "description" : "Virtual chocolate cake to fill your virtual tummy",
      "price" : [
      {
        "currency": "USD",
        "amount": "5.50"
      }, 
      {
        "currency": "BRL",
        "amount": "11.07"
      }],
      "defaultPrice": "USD",
      "productData": "my_product_id=123",
      "postbackURL": "http://developerserver.com/postback",
      "chargebackURL": "http://developerserver.com/chargeback"
    },
    "response" : {
      "transactionID": "123456123456123456", // transaction ID
      "reason": "refund"
    }
 }

More details about the chargeback notifications are explained in the Notifications section.

Apart from the navigator.mozPay() option for requesting refunds, the Payment Processor (BlueVia) SHOULD keep a list of transactions accessible via user profile, allowing the user to cancel the latest ones. A chargeback notification should be sent to the developer once a refund is requested by the user and executed by the Payment Processor systems. The way the developer handles the chargeback notification would depend on the nature of the sold digital good and it is developer's responsibility to cancel or remove it properly from the user's device. Go to Validating a receipt for information about how the Mozilla Marketplace deals with apps receipts.

Marketplace refunds for application purchases

The Marketplace must keep a purchase history allowing the user to cancel the latest transactions and request a refund for it. The way the Marketplace would handle the refund requests from the user would depend on the Payment Provider used for each specific transaction. Currently, the Marketplace is only supporting one Payment Provider: Telefónica BlueVia. The PayPal case got out of the scope of v1 release.

For the BlueVia use case, in order to request refunds for application purchases the Marketplace would use the same navigator.mozPay API. Just like for the Marketplace payment flow via BlueVia Payment Provider, the only difference to in-app refunds is that the Marketplace use the app as the issuer, instead of itself.

Once the user requests a refund for an application purchased, the Marketplace generates a refund request that contains the transactionID returned as result of the payment flow for that application. The marketplace can also add a chargeback URL, so it could receive notifications about the refund process result in this URL. The new chargeback URL is optional and you may found more info about this in the Notifications section. Finally, the marketplace should sign the refund request with the application secret.

 {
    "iss" : developerIdentifier,
    "aud" : "tu.com",
    "typ" : "tu.com/payments/refund/v1",
    "exp" : 1337370900,
    "iat" : 1337360900,
    "request" : {
      "refund" : "123456177777777", // transaction ID associated to app purchase flow
      "reason" : "Application refund",
      "chargebackURL" : "https://marketplace.mozilla.org/chargeback"
    }
 }

Once the refund request is processed and accepted by the Payment Provider, it would send the chargeback notification to the Marketplace. The Marketplace must notify the developer about this refund using the notification information that the developer may have provided during his registration process, if available.

Applications should be uninstalled from the user's device after canceling the associated transaction by invalidating the application receipt.

Notifications

Developer notifications

A developer that wants to order a payment and receive notifications about the payment and the potential refund related to that transaction has the following options:

  1. As part of his registration process, he may want to provide a default postback and a default chargeback URLs, so he would be notified about app purchases and refunds on this endpoints. This URLs would be provided and editable via the Mozilla Marketplace, which also would be responsible for notifying the developer about app purchases and refunds. This default URLs info would be shared with the Payment Provider, which would use it to notify the developer about in-app purchases or refunds related to in-app purchases.
  2. If the developer didn't provide his default postback and chargeback URLs or wants to temporary override this default URLs, he can also add new URLs to his payment request. If a postback URL is provided within the payment request, the Payment Provider would use this callback to notify the developer about the successful or failed transaction. If a chargeback URL is provided within the payment request, the Payment Provider would associate this URL with the transaction ID, so if a refund is requested with that transaction ID, the Payment Provider would use that chargeback URL to notify the developer about the refund (and not the default one stored for the developer, if available) unless 3.
  3. If a developer provides a new chargeback URL within his refund request, this last URL would be the one used by the Payment Provider to notify about the successful or failed refund.

So the basic idea is: the latest URL received by the Payment Provider is the last used for notifications.

Marketplace notifications

As you already know, the Marketplace would use the navigator.mozPay() to request payments and refunds as any other developer would. The main difference is that the Marketplace would request payments and refunds on behalf of the developer. So it would need to add the appID on its payment and refund requests to identify the developer.

Besides that, as the Marketplace wants to be notified about app purchases and refunds related to that purchases, it would need to use option 2 mentioned before. That means, it would need to include it postback and chargeback URL, so the Payment Provider would notify the Marketplace instead of the developer. Once the Marketplace is notified by the Payment Provider, it would need to notify the developer via the default URL that he might have provided.

Online payments from other networks

Users can pay over wifi connections if the Payment Provider integrates with BrowserID or a SMS verification flow is provided. In this case, payments actually can occur via other devices and the same BrowserID (e.g. by a user logged into a desktop browser with the same identity that is tied to a carrier account).

Developer control

The Payment Provider can expose an API to share aggregated transaction info with the Marketplace to allow developers to keep track of app sales from within the Marketplace. The Marketplace can aggregate this information from all the Payment Providers the developer signed up for for the particular app.

Payment Provider facing API

See the WebPaymentProvider spec for details on how to implement a payment provider for navigator.mozPay().

Testing

Test app

https://github.com/ferjm/Payment-tests

Testing against the Mock Payment Provider

The navigator.mozPay API is currently in mozilla-central and there is a dummy mock payment provider available for testing.

navigator.mozPay requires a list of allowed Payment Providers given in the form of user preferences. So first of all, you need to add the Mock Payment Provider information to your Gaia profile as a user preference: - Create a file named custom-prefs.js in the Gaia root directory. - Add the following user preferences:


user_pref("dom.payment.provider.0.name", "mockpayprovider");
user_pref("dom.payment.provider.0.description", "Mock Payment Provider");
user_pref("dom.payment.provider.0.type", "mock/payments/inapp/v1");
user_pref("dom.payment.provider.0.uri", "https://mockpayprovider.phpfogapp.com/?req=");
user_pref("dom.payment.provider.0.requestMethod", "GET");

Note that you may need to change the payment provider index (0 in the above preferences) according to already existing payment provider preferences. - Run make install-gaia

After adding the Mock Payment Provider information as a user preference you should be able to start testing.

An example of a valid payment request against the Mock Payment Provider would be:

{
 "iss": "123456789",
 "aud": "Mock Payment Provider",
 "typ": "mock/payments/inapp/v1",
 "exp": 1345259882,
 "iat": 1345256282,
 "request": {
   "name": "Piece of Cake",
   "description": "Virtual chocolate cake to fill your virtual tummy",
   "price":[ { "country":"US", "amount":"5.50", "currency":"USD" }, { "country":"BR", "amount":"8.50", "currency":"BRL" } ]
 }
}

Which results in the following JWT:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIxMjM0NTY3ODkiLCJhdWQiOiJNb2NrIFBheW1lbnQgUHJvdmlkZXIiLCJ0eXAiOiJtb2NrXC9wYXltZW50c1wvaW5hcHBcL3YxIiwiZXhwIjoxMzQ1MjU5ODgyLCJpYXQiOjEzNDUyNTYyODIsInJlcXVlc3QiOnsibmFtZSI6IlBpZWNlIG9mIENha2UiLCJkZXNjcmlwdGlvbiI6IlZpcnR1YWwgY2hvY29sYXRlIGNha2UgdG8gZmlsbCB5b3VyIHZpcnR1YWwgdHVtbXkiLCJwcmljZSI6W3siY291bnRyeSI6IlVTIiwiYW1vdW50IjoiNS41MCIsImN1cnJlbmN5IjoiVVNEIn0seyJjb3VudHJ5IjoiQlIiLCJhbW91bnQiOiI4LjUwIiwiY3VycmVuY3kiOiJCUkwifV19fQ.EaXnlL7LUlmYXUTty5ZkUQ7VZeCBa_edi2YXKPnjSl4

Testing against the BlueVia Payment Provider

  • Since the BlueVia Payment Provider is behind a Telefónica VPN, the first requirement is to get access to it. Unfortunately not everyone is allowed to access to the BlueVia servers and a specific request to the BlueVia team has to be done in order to request access.
  • Since B2G fails (Bug 769178) when accessing some HTTPS urls that have a certificate signed by an unknown CA (like the BlueVia one), apart from access to the BlueVia dev server, you would also need the BlueVia dev server certificates. BlueVia should probably be changing its certificate for a different one signed by a public CA, but until then, you would need to install the current certificates.
    • If you are testing on a B2G device, you can simply run this script (just run ./modifyCertDb.sh in Mac or Linux, or the .bat file in Windows) which would install the certificates and add the BlueVia payment provider information to the Gaia profile.
    • Unfortunately, there is not an automatic script for the B2G-desktop environment, and the certificate instalation requires the following steps:
      • From the shell that you are going to run B2G desktop do export NSS_DEFAULT_DB_TYPE=sql
      • Remove the key3.db and cert8.db files from your Gaia profile root.
      • Run B2G via ./b2g -profile <path-to-gaia-profile>
      • Open an HTTPS web page from the Gaia browser app.
      • Close B2G-desktop.
      • Download this zip file, extract its content and copy the key4.db, cert9.db and pkcs11.txt files to the Gaia profile root.
      • Launch B2G-desktop again. You should be able to navigate to https://webvpn.tid.es from the Gaia system app, that means that the certificates has been properly stored.
      • Add the following preferences to your Gaia profile (as explained in [Testing against a Mock Payment Provider]):

user_pref("dom.payment.provider.0.name", "blueviasimple");
user_pref("dom.payment.provider.0.description", "Telefónica BlueVia simple flow");
user_pref("dom.payment.provider.0.type", "tu.com/payments/v1/simplepay");
user_pref("dom.payment.provider.0.uri", "https://id.tda-qa-01.hi.inet/en/payments/v1/simplepay?req=");
user_pref("dom.payment.provider.0.requestMethod", "GET");
user_pref("dom.payment.provider.1.name", "bluevia");
user_pref("dom.payment.provider.1.description", "Telefónica BlueVia flow");
user_pref("dom.payment.provider.1.type", "tu.com/payments/v1/pay");
user_pref("dom.payment.provider.1.uri", "https://id.tda-qa-01.hi.inet/en/payments/v1/pay?req=");
user_pref("dom.payment.provider.1.requestMethod", "GET");

If everything went well, you should be able to start testing against BlueVia.

An example of a valid payment request against the BlueVia Payment Provider would be:

{
 "iss":"567744a02bf5af6a8c4c1c80d22fb2",
 "typ":"tu.com/payments/v1/pay",
 "exp":3337360897,
 "iat":1337360897,
 "request": {
   "name": "Piece of Cake",
   "description": "Virtual chocolate cake to fill your virtual tummy",
   "price":[ { "country":"BR", "amount":"1", "currency":"BRL" }, { "country":"ES", "amount":"0.01", "currency":"EUR" } ],
   "defaultPrice": "US",
   "productData": "my_product_id=1234&my_session_id=XYZ",
   "postbackURL": "http://developersserver.com/postback",
   "chargebackURL": "http://developerserver.com/chargeback"
 }
}

Which results in the following JWT:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiI1Njc3NDRhMDJiZjVhZjZhOGM0YzFjODBkMjJmYjIiLCJ0eXAiOiJ0dS5jb21cL3BheW1lbnRzXC92MVwvcGF5IiwiZXhwIjozMzM3MzYwODk3LCJpYXQiOjEzMzczNjA4OTcsInJlcXVlc3QiOnsibmFtZSI6IlBpZWNlIG9mIENha2UiLCJkZXNjcmlwdGlvbiI6IlZpcnR1YWwgY2hvY29sYXRlIGNha2UgdG8gZmlsbCB5b3VyIHZpcnR1YWwgdHVtbXkiLCJwcmljZSI6W3siY291bnRyeSI6IkJSIiwiYW1vdW50IjoiMSIsImN1cnJlbmN5IjoiQlJMIn0seyJjb3VudHJ5IjoiRVMiLCJhbW91bnQiOiIwLjAxIiwiY3VycmVuY3kiOiJFVVIifV0sImRlZmF1bHRQcmljZSI6IlVTIiwicHJvZHVjdERhdGEiOiJteV9wcm9kdWN0X2lkPTEyMzQmbXlfc2Vzc2lvbl9pZD1YWVoiLCJwb3N0YmFja1VSTCI6Imh0dHA6IFwvXC9kZXZlbG9wZXJzc2VydmVyLmNvbVwvcG9zdGJhY2siLCJjaGFyZ2ViYWNrVVJMIjoiaHR0cDogXC9cL2RldmVsb3BlcnNlcnZlci5jb21cL2NoYXJnZWJhY2sifX0.b6n2j--3vyi1szMqsyXkldeUK5G0HWv4w_G7u1dXmdY

Current implementation

Current implementation

[1] The payment confirmation screen will not be shown if the navigator.mozPay call contains only one valid payment request (Bug 793811)

[2] Once the payment flow is loaded within the trusted UI the chrome code injects in the payment flow content the necessary functions to notify the platform about the successfull or failed purchase.

Modules

DOM part in Gecko

Contains the common code that exposes the navigator.mozPay function to the DOM and that is supposed to be shared by all the platforms (B2G, Fennec, Firefox).

This code lives in dom/payment.

B2G Glue part in Gecko

Contains the specific B2G code that triggers the trusted UI creation to embed the payment flow iframe and that injects the required paymentSuccess() and paymentFailed() functions within the payment flow content.

It implements the nsIPaymentUIGlue interface


interface nsIPaymentUIGlueCallback
{
   void onresult(in DOMString result);
};

interface nsIPaymentUIGlue
{
   // The 'paymentRequestsInfo' contains the payment request information
   // for each JWT provided via navigator.mozPay call.    
   void confirmPaymentRequest(in jsval paymentRequestsInfo,
                              in nsIPaymentUIGlueCallback successCb,
                              in nsIPaymentUIGlueCallback errorCb);

   void showPaymentFlow(in nsIPaymentFlowInfo paymentFlowInfo,
                        in nsIPaymentUIGlueCallback errorCb);
};

This code lives in b2g/components and b2g/chrome/content.

Gaia part

Contains the require code to create, open and close the trusted UI and the payment confirmation screen.

This code lives in the Gaia system app, specifically apps/system/js/payment.js and apps/system/js/popup_manager.js

Communication

The communication between Gecko and Gaia is done via mozChromeEvent and mozContentEvent, which is a communication mechanism between chrome and the Gaia system app. mozChromeEvent are sent from chrome to content and mozContentEvent are sent from content to crhome. Where "sent" is used loosely here, since "broascast" is probably a better term. This communication is required to control the creation and closure of the trusted UI and to inject the required functions to notify the success or failure of the payment flow within the payment provider content.

See also