WebAPI/WebPayment: Difference between revisions
No edit summary |
No edit summary |
||
| Line 95: | Line 95: | ||
Here is a detailed explanation of the in-app payment JWT: | Here is a detailed explanation of the in-app payment JWT: | ||
;iss: | **'''iss''': The issuer of the JWT. This is the application key assigned during the app registration process for this specific payment provider (BlueVia). | ||
**'''typ''': 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''': Request object. | |||
*** '''price''': This is the price of the purchased product. | |||
*** '''currency''': This is the currency code for the price. | |||
*** '''name''': A short description of the product. | |||
*** '''description''': 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 <code>navigator.pay()</code> with this signed payment request. For example, the app might have a 'buy' button that triggers this method when clicked. Then <code>navigator.pay</code> method should take the signed payment JWT or an array of them. As a result of this call a [https://developer.mozilla.org/en/DOM/DOMRequest DOMRequest] object would be returned. The developer may use this DOMRequest object to monitor the progress of the operation. | |||
<code> | |||
let request = navigator.pay([signedJWT1, signedJWTn]); | |||
request.onsuccess = function () { | |||
[...] | |||
} | |||
request.onerror = function () { | |||
[...] | |||
} | |||
</code> | |||
* The <code>navigator.pay</code> method must open a Payment Provider selection screen based on the received JWTs, so the user can 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 (TU ID Connect 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 purchase is presented to the user for confirmation, with name, description and identifying information from TU ID Connect about the seller. | |||
* The user confirms the purchase or cancels it. | |||
* If the user cancels, the flow returns to the <code>DOMRequest.onerror</code> 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 plus a transaction identifier, and is signed with the seller's application secret. | |||
<code> | |||
{ | |||
iss : sellerIdentifier, | |||
typ : "tu.com/payments/inapp/v1”, | |||
exp : int(time.time() + 3600), | |||
iat : int(time.time()), | |||
request : { | |||
name : "Piece of Cake", | |||
description : "Virtual chocolate cake to fill your virtual tummy", | |||
price : "10.50", | |||
currencyCode : "USD", | |||
productData => "my_product_id=123" | |||
postbackURL => “http://developerserver.com/postback”, | |||
chargebackURL => “http://developerserver.com/chargeback” | |||
} | |||
response: { | |||
transactionID: "123456123456123456" | |||
} | |||
} | |||
</code> | |||
* To verify that the purchase is valid, the application server first needs to decode 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. | |||
Revision as of 12:44, 19 July 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.pay' implementation.
Currently only implemented for B2G.
Proposed API
Expose the pay function to the navigator object
interface nsIDOMNavigatorPayment
{
DOMRequest pay(in jsval jwts);
}
Proposers
Andreas Gal and Fernando Jiménez.
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.pay function.
An OWA should be able to access the in-app web payments services using an API (navigator.pay) 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.pay()' 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.pay(). - 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) or BrowserID assertion in the B2G scenario).
- The buyer completes or cancels the purchase. (Note that the Payment Provider might 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.pay()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.payfunction 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.).
- TU ID Connect
- 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 transmitter over the network, the user should be registered and logged in TU ID Connect (Telefónica's customers portal).
User sign-up and sign-in in TU 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.pay() 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.
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,
"typ" : "tu.com/payments/inapp/v1",
"exp" : int(time.time() + 3600),
"iat" : int(time.time()),
"request" :{
"name" : "Piece of Cake",
"description" : "Virtual chocolate cake to fill your virtual tummy",
"price" : "10.50",
"currencyCode" : "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: 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: Request object.
- price: This is the price of the purchased product.
- currency: This is the currency code for the price.
- name: A short description of the product.
- description: 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.pay()with this signed payment request. For example, the app might have a 'buy' button that triggers this method when clicked. Thennavigator.paymethod 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.pay([signedJWT1, signedJWTn]);
request.onsuccess = function () {
[...]
}
request.onerror = function () {
[...]
}
- The
navigator.paymethod must open a Payment Provider selection screen based on the received JWTs, so the user can 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 (TU ID Connect 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 purchase is presented to the user for confirmation, with name, description and identifying information from TU ID Connect about the seller.
- The user confirms the purchase or cancels it.
- If the user cancels, the flow returns to the
DOMRequest.onerrorcallback. - 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 plus a transaction identifier, and is signed with the seller's application secret.
{
iss : sellerIdentifier,
typ : "tu.com/payments/inapp/v1”,
exp : int(time.time() + 3600),
iat : int(time.time()),
request : {
name : "Piece of Cake",
description : "Virtual chocolate cake to fill your virtual tummy",
price : "10.50",
currencyCode : "USD",
productData => "my_product_id=123"
postbackURL => “http://developerserver.com/postback”,
chargebackURL => “http://developerserver.com/chargeback”
}
response: {
transactionID: "123456123456123456"
}
}
- To verify that the purchase is valid, the application server first needs to decode 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.