The PaySwarm Web platform is an open web standard that enables Web browsers and Web devices to perform Universal Web Payment. PaySwarm enables the people that create digital content such as blog posts, music, film, episodic content, photos, virtual goods, and documents to distribute their creations through their website and receive payment directly from their fans and customers. The technology is designed to be integrated directly into blogging platforms, content management systems and general purpose websites. The standard can be applied to the entire content distribution lifecycle, from asset description, to product listings, to licenses, contracts and financial transactions. Features include the ability to exchange money, transact individual sales, subscriptions and micropayments.
The PaySwarm Web platform is an open web standard that enables Web browsers and Web devices to perform Universal Web Payment. PaySwarm enables the people that create digital content such as blog posts, music, film, episodic content, photos, virtual goods, and documents to distribute their creations through their website and receive payment directly from their fans and customers. The technology is designed to be integrated directly into blogging platforms, content management systems and general purpose websites.
The technology is provided as an open web platform, which is a combination of technology that is patent-free, royalty-free, published in a free specification, using well-defined protocols and other open technologies. The entire PaySwarm standard, like HTML, HTTP, and JavaScript, is an open web platform. Almost every successful Web technology is built and released in this way.
PaySwarm supports Micropayments. The standard assumes that customers do not want to be bothered to reach for their wallet every time they need to spend a couple of cents, or even a couple of dollars. Micropayment in this case, specifically refers to the ability to automatically distribute payments in increments of up to 1/100,000th of a cent to anybody listed in PaySwarm digital contracts.
It is the goal of this specification to create an environment that is friendly to content creators and customers alike. Distribution of digital goods is becoming an increasing part of the Web and therefore compensation for these digital goods must be as easy to perform as downloading the digital goods. The PaySwarm specification works with the architecture of the Web to deliver a solution that is universal across websites, industries and countries.
There are three primary participants in a PaySwarm transaction; the buyer, the vendor, and the authority.
In order for a universal payment system to work seamlessly, there must be a
universal way of identifying things in the environment. This
specification uses Internationalized Resource Identifiers [[!IRI]] to
refer to things on the network. These things can be a personal identity
(https://example.com/people/bob),
financial account information
(https://example.com/people/bob/accounts/42), public cryptography
keys (https://example.com/people/bob/keys/14), assets, licenses
and a variety of other pieces of long-lived information that exists on the Web.
By naming these things with long-lived unique identifiers, it becomes possible
to create a decentralized but stable universal payment architecture.
An
A
A
A
A
A
A
PaySwarm builds on a number of successful Internet and Web technologies. These technologies are introduced in this section.
REpresentational State Transfer [[REST]] is the architectural style that underpins the World Wide Web. It consists of a set of constraints to ensure that servers, gateways, proxies and clients may interact in a way that is predictable. Systems that are designed with this architecture in mind are called RESTful systems. PaySwarm is designed to be RESTful by ensuring that the constraints of REST are applied to all transactions performed via PaySwarm systems.
JavaScript Object Notation for Linking Data [[!JSON-LD]] is a lightweight Linked Data format. It is easy for humans to read and write. It is easy for machines to parse and generate. It is based on the already successful JSON format and provides a way to help JSON data interoperate at Web-scale. If you are already familiar with JSON, writing JSON-LD is very easy. There is a smooth migration path from the JSON you use today, to the JSON-LD you will use in the future. These properties make JSON-LD an ideal Linked Data interchange language for JavaScript environments, Web services, and JSON document-based databases.
The Advanced Encryption Standard (AES) [[!FIPS-197]] is a world standard adopted by the United States Government and used to secure a vast majority of the commercial transactions over the Internet via OpenSSL. Since much of the data exchanged over PaySwarm participants is sensitive, it is important that a strong cryptography suite is utilized to digitally sign and transfer the messages.
Web sites are largely implemented on top of the HyperText Markup Language (HTML). This format is known to be fairly easy to author and publish on the Web. In addition to being easy to publish, it is also important that data published via HTML can be easily read by machines without placing an undue burden on Web authors. Publishing structured data in a decentralized manner also requires a language that is capable of being both expressive and deterministic. The Resource Description Framework in attributes [[!RDFA-CORE]] extends HTML [[!HTML-RDFA]] to allow structured data to be expressed via HTML, but in a way that is easy for Web developers to author.
All communication between software operating under this specification is intended to perform according to REST [[REST]] principles. Additionally, since PaySwarm implements a financial system, the security of messages and data is of paramount importance. A security breach at certain points during the algorithms described in the following sections may introduce attack vectors that criminals could utilize to steal from or cause financial harm to the systems or people involved. However, excellent security does not have to come at a high cost. PaySwarm has been designed so that many parts of the system can be implemented in a way that does not incur significant effort, recurring costs, or financial outlay.
This specification requires that a
An invalid certificate or TLS error or any kind MUST result in the API
call exiting immediately and not performing the requested
action. All API requests sent to the
The following terminology is used to describe concepts used to generate and secure messages in the system. Many of these terms are borrowed from public/private key cryptography. A more complete description of public/private cryptography can be found in The Advanced Encryption Standard [[AES]].
The following algorithm ensures that the originator of an API call can be
verified as long as the public key can be retrieved by the receiver. A
sec:signature key-value pair from the top-level of the
2011-09-23T20:21:34Z.
Append the sec:signature key to the @typesec:JsonLdSignaturedc:createdsec:responseTokenjf793ksj72jkf-78p82qpj87dnd2f839. See
The Response Token section to understand
more about how this value is used to prevent replay attacks and its accepted
limitations.
sec:publicKeysec:signatureValue
The following example shows an input
*** message
{
"@context": "http://purl.org/payswarm/v1",
"dc:title": "Hello World!"
}
*** signed message
{
"@context": "http://purl.org/payswarm/v1",
"dc:title": "Hello World!",
"sec:signature":
{
"@type": "sec:JsonLdSignature",
"dc:created": "2011-09-23T20:21:34Z",
"sec:signer": "http://payswarm.example.com/i/john/keys/5",
"sec:signatureValue": "OGQzNGVkMzVm4NTIyZTkZDYMmMzQzNmExMgoYzI43Q3ODIyOWM32NjI="
}
}
In order to ensure a secure communication environment the following algorithm
SHOULD be used to verify all request signatures in the system. A
sec:signature value
from the dc:created key in the
sec:signer value. The
The following algorithm ensures that a message intended for a particular
recipient can be obfuscated such that only the intended recipient can read the
message. A
@typesec:EncryptedMessagesec:datasec:encryptionKeysec:cipherrsa-aes-128-cbc.
sec:ivsec:publicKeyThe following example shows a typical input message and what an encrypted message looks like when generated using the algorithm above.
*** message
{
"@type": "ps:Preferences"
"com:currency": "USD",
"com:minimumAmount": "0.05",
"com:maximumRate": "10.0",
"com:destination": "https://example.com/people/manu/accounts/article-sales",
"sec:publicKey": "http://payswarm.example.com/i/manu/keys/23",
"ps:license": "http://purl.org/payswarm/licenses/blogging",
"ps:licenseHash": "961ec496092bf6ee08d6255d96069b5186332689",
}
*** encrypted message
{
"@type": "sec:EncryptedMessage",
"sec:data": "VTJGc2RHVmtYMThOY3h2dnNVN290Zks1dmxWc3labi9sYkU0TGloRTdxY0dpblE4OHgrUXFNNi9l\n↩
a1JMWjdXOApRSGtrbzh6UG5XOFo3WWI4djJBUG1abnlRNW5CVGViWkRGdklpMEliczNWSzRQTGdB\n↩
UFhxYTR2aWFtemwrWGV3Cmw0eFF4ancvOW85dTlEckNURjMrMDBKMVFubGdtci9abkFRSmc5UjdV\n↩
Rk55ckpYalIxZUJuKytaQ0luUTF2cUwKcm5vcDU1eWk3RFVqVnMrRXZZSkx6RVF1VlBVQ0xxdXR4\n↩
L3lvTWd4bkdhSksxOG5ZakdiekJxSGxOYm9pVStUNwpwOTJ1Q0Y0Q2RiR1NqL0U3OUp4Vmh6OXQr\n↩
Mjc2a1V3RUlNY3o2Z3FadXZMU004KzRtWkZiakh6K2N5a1VVQ2xHCi9RcTk3b2o3N2UrYXlhZjhS\n↩
ZmtEZzlUeWk3Q2szREhSblprcy9WWDJWUGhUOEJ5c3RiYndnMnN4eWc5TXhkbHoKUkVESzFvR0FJ\n↩
UDZVQ09NeWJLTGpBUm0zMTRmcWtXSFdDY29mWFNzSGNPRmM2cnp1Wko0RnVWTFNQMGROUkFRRgpB\n↩
bFQ0QUpPbzRBZHpIb2hpTy8vVGhNOTl1U1ZER1NPQ3graFAvY3V4dGNGUFBSRzNrZS8vUk1MVFZO\n↩
YVBlaUp2Ckg4L1ZWUVU4L3dLZUEyeTQ1TzQ2K2lYTnZsOGErbGg0NjRUS3RabktFb009Cg==",
"sec:encryptionKey": "uATtey0c4nvZIsDIfpFffuCyMYGPKRLIVJCsvedE013SpEJ+1uO7x6SK9hIG9zLWRlPpwmbar2bt\n↩
gTX5NBzYC5+c5ZkXtM1O8REwIJ7wmtLdumRYEbr/TghFl3pAgXhv0mVt8XZ+KLWlxMqXnrT+ByNw\n↩
z7u3IxpqNVcXHExjXQE=",
"sec:cipher": "rsa-aes-128-cbc",
"sec:iv": "vcDU1eWTy8vVGhNOszREhSblFVqVnGpBUm0zMTRmcWtMrRX==",
"sec:publicKey": "http://payswarm.example.com/i/manu/keys/23"
}
The following algorithm is used to decrypt an encrypted response. The input
is an
sec:encryptionKey value and using the sec:publicKey to decrypt the base-64 decoded value.
sec:iv value and then using the sec:publicKey to decrypt the base-64 decoded value.
sec:cipher to the sec:data value. Use the
Since this specificationd describes a financial system, the security of the communication in the system is of utmost importance. The following section describes security considerations that developers implementing this specification should be aware of in order to create secure software.
The sec:responseToken mechanism is used in order to prevent
replay attacks, but implementers must be aware that it is not capable of
preventing man-in-the-middle attacks. Only a full end-to-end encryption channel
is capable of accomplishing that feat and if implementers are concerned about
man-in-the-middle attacks, they are strongly advised to run all callbacks
over HTTPS.
While implementation of the response token to prevent replay attacks is left as an exercise to the developer, it is advised that it is treated as a one-time token. That is, when a response token is sent from one peer to another peer, the sender must note the response token in an internal database. When the response token is returned in an encrypted message, the response token must be deleted from the internal database so all successive calls using the same response token will fail. This simple behavior prevents replay attacks and is simpler to implement than a security nonce.
To further increase security, it is advised that the response token is tied to the originating client's IP address in some way. The resulting response callback should be executed by the same client's IP address, thus many classes of man-in-the-middle attacks can be prevented, requiring quite a sophisticated attack in order to hijack the response. Note that the hijacker will not be able to modify the response, but merely callback-jack the response. The result of the callback-jack would be fairly benign in most cases - gaining access to an article that was purchased by the original user agent that initiated the request. The original purchaser will still have access to the article, so the only damage done is the ability to view or download an article as someone else. If this is a concern to implementers, they are advised to purchase a valid SSL certificate and ensure that all callbacks to their site occur over SSL.
The registration process is necessary in order to specify details about the participants in a PaySwarm transaction.
There are a number of terms that are used during the course of the registration process.
payswarm-v1-config.
The document MUST be available in JSON-LD compacted form and MUST use the
http://purl.org/payswarm/v1 JSON-LD context. The following
keys MUST be present in the published document;
ps:publicKeyService, ps:licenseService, and
ps:transactionService.
In order for a
https://example.com/people/jane.https://example.com/people/jane/accounts/primary.
In order for a
https://example.com/people/manu.https://example.com/people/manu/accounts/article-sales.
Since all
https://example.com/ with the
payswarm-v1-config suffix.
For example, the previous https://example.com/payswarm-v1-config.Accept header set to
application/ld+json; form=compacted. The
http://purl.org/payswarm/v1.public-key, is the
URL-encoded X.509 PEM-encoded public key. The second parameter,
registration-callback,
is the URL-encoded registration-callback IRI via a POST
initiated by the com:currency, com:minimumAmount,
com:maximumRate, com:destination,
sec:publicKey, ps:license and
ps:licenseHash.
registration-callback via an HTTP POST request that is initiatited
by the
The example below shows the full protocol-level exchange between the
--------------------------------- Step #1 -----------------------------------
*** Request: user agent -> publishing agent
POST /register-blog HTTP/1.1
Host: publisher.example.org
Content-Length: 47
Content-Type: application/x-www-form-urlencoded
payswarm-authority=http%3A%2F%2Fpayswarm.example.com%2F
*** publishing agent generates and stores public/private keypair
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDptIkqrXhx7YVGsBZ5fY/Lz0il
0LXJrhUY43V/lLWdRf7JXY6tcgA5AmwNGZtJRyH79QXCJn+BAHUtl6gX2gvjs8N2
B5u4m0LtXyaFWtbQV9+hY3JRLOBiydPeXLgsnLwKiJ9v4CNXSNA5wT8vYGXiqq0B
US89y0M909ZTj2zDQwIDAQAB
-----END PUBLIC KEY-----
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDptIkqrXhx7YVGsBZ5fY/Lz0il0LXJrhUY43V/lLWdRf7JXY6t
cgA5AmwNGZtJRyH79QXCJn+BAHUtl6gX2gvjs8N2B5u4m0LtXyaFWtbQV9+hY3JR
LOBiydPeXLgsnLwKiJ9v4CNXSNA5wT8vYGXiqq0BUS89y0M909ZTj2zDQwIDAQAB
AoGALNmBrVgHEk4T0qH+XihTjThlZ7Tq/h5TXChipy5BwEHriHdU50JGeqpVVBpC
68gj5Hd8OGss8vPEiRBeqN0mhJlRaX5ijyFp2n8+7DhfOIVhCd1MXCGQPTrdXIo5
OOQECSplnALZfKr0VC4TBeW+oUZGMoG4rRSM5DfyPFJtlzECQQD8DkWBkhRsP1An
3qfZR8oUkvbaVg9jsCNvoBazYSS3OhsZ96ZSTyf9hJn28wGJmShuZA2eL5XjuTY4
m0fQDhj5AkEA7VzAqKOx5zlFTWXMIzn29uB59m4yJ7UwCyc7tisQA16I8B2HzJzZ
saipkpU2RUYaBrjtWaiVNtyXvZ7mccJpGwJBAMyE4/8bwfiHcwm2z+ktKBqDmUtW
E0ynKkmz01ef1kPaIQ1z9f/JfMBnrOpFCZVVsgnIo4gcQnox2X4a+S0nkzkCQBre
xCSTG2Gclx7S5lAakL2T3dqq0Nyz4zNwBo9xwodPHVtpTGU6YF5/RGsGnzUqYWnf
Z2cd8X5bbIYXxeic5H8CQQCcBOtOdrq9FXsEnyhG5gQXvGdxEAmM2eUs1g8E8kgx
KBTHOaBRQMgvjsdA/obrs7D0HrEbQqGOy7JBYGWZTsiI
-----END RSA PRIVATE KEY-----
--------------------------------- Step #2 -----------------------------------
*** Request: publishing agent -> authority
GET /payswarm-v1-config HTTP/1.1
Host: payswarm.example.com
Accept: application/ld+json,*/*;q=0.1
*** Response: publishing agent <- authority
HTTP/1.1 200 OK
Connection: close
Content-Length: 6075
Content-Type: application/ld+json
Date: Wed, 21 Sep 2012 22:30:16 GMT
Host: payswarm.example.com
Server: Apache/2.2.19 (Debian)
{
"@context": "http://purl.org/payswarm/v1",
"@id": "http://payswarm.example.com/i/authority",
"ps:registrationService": "http://payswarm.example.com/api/v1/applications",
"ps:publicKeyService": "http://payswarm.example.com/api/v1/keys",
"ps:licenseService": "http://payswarm.example.com/api/v1/licenses",
"ps:transactionService": "http://payswarm.example.com/api/v1/contracts"
}
--------------------------------- Step #3 -----------------------------------
*** Redirect: user agent <- publishing agent
HTTP/1.1 303 See Other
Location: https://payswarm.example.com/api/v1/keys?public-key=↩
-----BEGIN+PUBLIC+KEY-----%0A↩
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDptIkqrXhx7YVGsBZ5fY%2FLz0il%0A↩
0LXJrhUY43V%2FlLWdRf7JXY6tcgA5AmwNGZtJRyH79QXCJn%2BBAHUtl6gX2gvjs8N2%0A↩
B5u4m0LtXyaFWtbQV9%2BhY3JRLOBiydPeXLgsnLwKiJ9v4CNXSNA5wT8vYGXiqq0B%0A↩
US89y0M909ZTj2zDQwIDAQAB%0A↩
-----END+PUBLIC+KEY-----↩
®istration-callback=http%3A%2F%2Fpublisher.example.org%2Fregistration-complete?nonce=pn9sueh43jefa
Content-Type: text/html
Content-Length: 174
<html>
<head>
<title>Identity Registration</title>
</head>
<body>
<h1>Public Key Registration</h1>
<p>You must now go to your authority and
<a href="http://payswarm.example.com/api/v1/keys?public-key=↩
-----BEGIN+PUBLIC+KEY-----%0A↩
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDptIkqrXhx7YVGsBZ5fY%2FLz0il%0A↩
0LXJrhUY43V%2FlLWdRf7JXY6tcgA5AmwNGZtJRyH79QXCJn%2BBAHUtl6gX2gvjs8N2%0A↩
B5u4m0LtXyaFWtbQV9%2BhY3JRLOBiydPeXLgsnLwKiJ9v4CNXSNA5wT8vYGXiqq0B%0A↩
US89y0M909ZTj2zDQwIDAQAB%0A↩
-----END+PUBLIC+KEY-----↩
®istration-callback=http%3A%2F%2Fpublisher.example.org%2Fregistration-complete?nonce=pn9sueh43jefa">
register your identification information</a>
there.</p>
</body>
</html>
--------------------------------- Step #4 -----------------------------------
*** This step consists of a series of UI interactions and is thus not
*** specified in this specification.
--------------------------------- Step #5 -----------------------------------
*** The authority creates a configuration object to return back
*** to the publishing agent
{
"@type": "ps:Preferences"
"com:currency": "USD",
"com:minimumAmount": "0.05",
"com:maximumRate": "10.0",
"com:destination": "https://example.com/people/manu/accounts/article-sales",
"sec:publicKey": "http://payswarm.example.com/i/manu/keys/23",
"ps:license": "http://purl.org/payswarm/licenses/blogging",
"ps:licenseHash": "961ec496092bf6ee08d6255d96069b5186332689",
}
*** The configuration object is then encrypted and sent to the
*** registration-callback specified in the registration request above.
POST registration-complete?nonce=pn9sueh43jefa HTTP/1.1
Host: publisher.example.org
Content-Length: 47
Content-Type: application/ld+json
{
"@type": "sec:EncryptedMessage",
"sec:data": "VTJGc2RHVmtYMThOY3h2dnNVN290Zks1dmxWc3labi9sYkU0TGloRTdxY0dpblE4OHgrUXFNNi9l\n↩
a1JMWjdXOApRSGtrbzh6UG5XOFo3WWI4djJBUG1abnlRNW5CVGViWkRGdklpMEliczNWSzRQTGdB\n↩
UFhxYTR2aWFtemwrWGV3Cmw0eFF4ancvOW85dTlEckNURjMrMDBKMVFubGdtci9abkFRSmc5UjdV\n↩
Rk55ckpYalIxZUJuKytaQ0luUTF2cUwKcm5vcDU1eWk3RFVqVnMrRXZZSkx6RVF1VlBVQ0xxdXR4\n↩
L3lvTWd4bkdhSksxOG5ZakdiekJxSGxOYm9pVStUNwpwOTJ1Q0Y0Q2RiR1NqL0U3OUp4Vmh6OXQr\n↩
Mjc2a1V3RUlNY3o2Z3FadXZMU004KzRtWkZiakh6K2N5a1VVQ2xHCi9RcTk3b2o3N2UrYXlhZjhS\n↩
ZmtEZzlUeWk3Q2szREhSblprcy9WWDJWUGhUOEJ5c3RiYndnMnN4eWc5TXhkbHoKUkVESzFvR0FJ\n↩
UDZVQ09NeWJLTGpBUm0zMTRmcWtXSFdDY29mWFNzSGNPRmM2cnp1Wko0RnVWTFNQMGROUkFRRgpB\n↩
bFQ0QUpPbzRBZHpIb2hpTy8vVGhNOTl1U1ZER1NPQ3graFAvY3V4dGNGUFBSRzNrZS8vUk1MVFZO\n↩
YVBlaUp2Ckg4L1ZWUVU4L3dLZUEyeTQ1TzQ2K2lYTnZsOGErbGg0NjRUS3RabktFb009Cg==",
"sec:encryptionKey": "uATtey0c4nvZIsDIfpFffuCyMYGPKRLIVJCsvedE013SpEJ+1uO7x6SK9hIG9zLWRlPpwmbar2bt\n↩
gTX5NBzYC5+c5ZkXtM1O8REwIJ7wmtLdumRYEbr/TghFl3pAgXhv0mVt8XZ+KLWlxMqXnrT+ByNw\n↩
z7u3IxpqNVcXHExjXQE=",
"sec:cipher": "aes-128-cbc",
"sec:iv": "vcDU1eWTy8vVGhNOszREhSblFVqVnGpBUm0zMTRmcWtMrRX==",
"sec:publicKey": "http://payswarm.example.com/i/manu/keys/23"
}
registration-callback IRI to protect the
The simplest exchange of value that can happen in the PaySwarm system is a
There are a number of terms that are used during the course of processing a transaction.
ps:transactionService key in
the domain's PaySwarm configuration file. The configuration file can be fetched
by performing an HTTP GET request on the
There are two ways in which a Transaction may be initiated via a
ps:Transaction. The normative algorithm for performing this
operation is detailed below. In both approaches, the
ps:Transaction entry in all of the accounts associated in the
The normative algorithm for performing an
@contexthttp://purl.org/payswarm/v1
or a list containing that context IRI as the first member, where subsequent
context declarations MUST NOT override any values in the first member.
@typeps:Transaction.
com:transfer@typeps:Transfer.
com:amountcom:currencycom:sourcecom:amount will
be withdrawn.
com:destinationcom:amount
will be deposited.
rdfs:comment@idcom:amountcom:currencycom:date
The example below shows the full protocol-level exchange between the
--------------------------------- Step #1 -----------------------------------
*** Agent creates a Transaction object
{
"@type": "ps:Transaction"
"ps:transfer":
{
"@type": "ps:Transfer",
"com:amount": "7.50",
"com:currency": "USD",
"com:source": "https://bluebank.com/people/john/accounts/party-funds",
"com:destination": "https://redbank.com/people/jane/accounts/hosting",
"rdfs:comment": "Chipping in for the Pizza Party tomorrow."
}
}
--------------------------------- Step #2 -----------------------------------
*** Agent signs the Transaction object
{
"@type": "ps:Transaction"
"ps:transfer":
{
"@type": "ps:Transfer",
"com:amount": "7.50",
"com:currency": "USD",
"com:source": "https://bluebank.com/people/john/accounts/party-funds",
"com:destination": "https://redbank.com/people/jane/accounts/hosting",
"rdfs:comment": "Chipping in for the Pizza Party tomorrow."
},
"sec:signature":
{
"@type": "sec:JsonLdSignature",
"dc:created": "2011-09-23T20:21:34Z",
"sec:signer": "http://payswarm.example.com/i/john/keys/5",
"sec:signatureValue": "ExMgoDIyOGQzNGVkMzVmmMzYzI43Q3OQzNmOWM32Nj4NTIyZTkZDYMI="
}
}
---------------------------------- Step #3 ----------------------------------
*** Agent HTTPS POSTs the Transaction object to the authority
POST transactions HTTP/1.1
Host: bluebank.com
Content-Length: 634
Content-Type: application/ld+json
{
"@type": "ps:Transaction"
"ps:transfer":
{
"@type": "ps:Transfer",
"com:amount": "7.50",
"com:currency": "USD",
"com:source": "https://bluebank.com/people/john/accounts/party-funds",
"com:destination": "https://redbank.com/people/jane/accounts/hosting",
"rdfs:comment": "Chipping in for the Pizza Party tomorrow."
},
"sec:signature":
{
"@type": "sec:JsonLdSignature",
"dc:created": "2011-09-23T20:21:34Z",
"sec:signer": "http://bluebank.com/people/john/keys/5",
"sec:signatureValue": "ExMgoDIyOGQzNGVkMzVmmMzYzI43Q3OQzNmOWM32Nj4NTIyZTkZDYMI="
}
}
---------------------------------- Step #4 ----------------------------------
*** authority processes the transaction and returns the finalized
*** transaction to the Agent
Cache-Control:no-cache, must-revalidate, max-age=0
Content-Length: 728
Content-Type: application/ld+json
{
"@id": "https://bluebank.com/transactions/20110923f72b8ca3",
"@type": "ps:Transaction",
"com:amount": "7.65",
"com:currency": "USD",
"com:date": "2011-09-23T20:21:35Z",
"ps:transfer":
[{
"@type": "ps:Transfer",
"com:amount": "7.50",
"com:currency": "USD",
"com:source": "https://bluebank.com/people/john/accounts/party-funds",
"com:destination": "https://redbank.com/people/jane/accounts/hosting",
"rdfs:comment": "Chipping in for the Pizza Party tomorrow."
},
{
"@type": "ps:Transfer",
"com:amount": "0.15",
"com:currency": "USD",
"com:source": "https://bluebank.com/people/john/accounts/party-funds",
"com:destination": "https://bluebank.com/accounts/processing-fees",
"rdfs:comment": "Chipping in for the Pizza Party tomorrow."
}]
}
The simplest purchase process includes four distinct steps; publishing an
While it is possible to express
An
The following example describes a web page
{
"@context": "http://purl.org/payswarm/v1",
"@id": "http://example.org/articles/1#asset",
"@type": ["ps:Asset", "ps:WebPage"],
"dc:title": "PaySwarm in Practice",
"dc:description": "This article covers how to use PaySwarm on your Website.",
"dc:creator":
{
"@type": "foaf:Organization",
"foaf:name": "Digital Bazaar, Inc.",
}
"ps:contentUrl": "http://example.org/articles/1",
"ps:validFrom": "2010-11-28T00:00:00Z",
"ps:validUntil": "2011-11-28T00:00:00Z"
"sec:signature":
{
"@type": "sec:JsonLdSignature",
"dc:created": "2010-11-28T00:00:00Z",
"sec:signer": "https://payswarm.example.com/i/digital-bazaar#key-5",
"sec:signatureValue": "OWM3YzI4OGQzNGVkMzV...IyZTk2MzQzNmExMgo="
}
}
In order to publish this asset on a Web page, a http://example.org/articles/1-purchase IRI:
<html>
<head>
<title>Buy: PaySwarm in Practice</title>
</head>
<body prefix="dc: http://purl.org/dc/terms/
foaf: http://xmlns.com/foaf/0.1/
ps: http://purl.org/payswarm#
sec: http://purl.org/security#
xsd: http://www.w3.org/2001/XMLSchema#">
<article about="http://example.org/articles/1#asset" typeof="ps:Asset ps:WebPage">
<h1 property="dc:title">PaySwarm in Practice</h1>
by
<h2 property="dc:creator" typeof="foaf:Organization">
<span property="foaf:name">Digital Bazaar, Inc.</span>
</h2>
<p property="dc:description">This article covers how to use PaySwarm on your Website.</p>
<a property="ps:contentUrl" href="http://example.org/articles/1">permalink</a>
<input type="button" onclick="doPurchase();">Purchase Access to the Article</input>
<input type="button" onclick="toggleDetails();">Details</input>
<div class="article-details hidden-by-default">
This asset publication is valid from
<span property="ps:validFrom" content="2010-11-28T00:00:00Z" datatype="xsd:dateTime">today</span>
until a
<span property="ps:validTo" content="2011-11-28T00:00:00Z" datatype="xsd:dateTime">year from today</span>.
<div property="sec:signature" typeof="sec:JsonLdSignature">
Signed on
<span property="dc:created" content="2010-11-28T00:00:00Z" datatype="xsd:dateTime">November 28th 2010</span>
by
<a property="sec:signer" href="https://payswarm.example.com/i/digital-bazaar#key-5">Digital Bazaar</a>:
<span property="sec:signatureValue">OWM3YzI4OGQzNGVkMzV...IyZTk2MzQzNmExMgo=</span>
</div>
</div>
</article>
</body>
</html>
It may not initially be clear why an
The example above demonstrates how the information expressed as [[!JSON-LD]] earlier in this section can be expressed as HTML+RDFa [[!HTML-RDFA]]. The rest of this specification will not express information using both mechanisms, but will use [[!JSON-LD]] markup for the sake of brevity even if the information being expressed is meant to be expressed in RDFa.
A
The following example describes a very simple license for personal use.
{
"@context": "http://purl.org/payswarm/v1",
"@id": "http://payswarm.example.com/licenses/personal-use",
"@type": "ps:License",
"dc:format": "text/html",
"ps:licenseTemplate": "This personal use license allows you to save the
purchased asset onto any device that you own for your personal enjoyment
and make up to <span property=\"ex:physicalCopies\" /> printed
copies of the work for personal use."
"ps:licenseTerms":
{
"ex:physicalCopies": 5
}
}
A
The following example describes an
{
"@context": "http://purl.org/payswarm/v1",
"@id": "http://example.com/articles/1#listing",
"@type": ["gr:Offering", "ps:Listing"],
"com:payee":
[
{
"@id": "http://example.com/articles/1#listing-payee",
"@type": "com:Payee",
"com:currency": "USD",
"com:destination": "https://payswarm.example.com/i/bob/accounts/primary",
"com:rate": "0.05",
"com:rateType": "com:FlatAmount",
"rdfs:comment": "Payment for PaySwarm in Practice by Digital Bazaar."
}
],
"com:payeeRule":
[
{
"@type": "com:PayeeRule",
"com:destinationOwnerType": "ps:Authority",
"com:maximumRate": "10",
"com:rateType": "com:InclusivePercentage"
}
],
"ps:asset": "http://example.com/articles/1#asset",
"ps:assetHash": "14618b56ff597a2fed560db9aa0610fe442106a4",
"ps:license": "http://payswarm.example.com/licenses/blogging",
"ps:licenseHash": "0d8866836917f8ef58af44accb6efab9a10610ad",
"sec:signature":
{
"@type": "ps:JsonLdSignature",
"dc:created": "2011-03-02T00:00:00Z",
"dc:creator": "https://payswarm.example.com/i/bob/keys/4",
"sec:signatureValue": "KXtwA5kXZBJzj1rkPMJmGDROjM+fpi2cJIB+Xqf10="
},
"ps:validFrom": "2011-03-02T00:00:00+0000",
"ps:validUntil": "2011-03-03T00:00:00+0000"
}
A normal purchase, as opposed to an automatic purchase, is typically performed
via a Web browser-based
There are a number of terms that are used during the course of the purchase process.
The normative algorithm for performing a purchase is expressed below.
listinglisting-hashcallbackreferencenonce@contexthttp://purl.org/payswarm/v1
or a list containing that context IRI as the first member, where subsequent
context declarations MUST NOT override any values in the first member.
@typeps:Receipt.
ps:preferenceps:preAuthorization - The ps:contract@typeps:Contract.
ps:assetps:assetHashcom:referenceps:licenseps:licenseHashps:listingps:listingHashps:assetAcquirercallback IRI supplied by the
An automatic purchase is one where a
There are a number of terms that are used during the course of the purchase process.
The automatic purchase algorithm is outlined below:
@contexthttp://purl.org/payswarm/v1
or a list containing that context IRI as the first member, where subsequent
context declarations MUST NOT override any values in the first member.
@typeps:PurchaseRequest.
ps:listingps:listingHashps:assetAcquirercom:reference@contexthttp://purl.org/payswarm/v1
or a list containing that context IRI as the first member, where subsequent
context declarations MUST NOT override any values in the first member.
@typeps:Receipt.
ps:contract@typeps:Contract.
ps:assetps:assetHashcom:referenceps:licenseps:licenseHashps:listingps:listingHashps:assetAcquirer
A
The following example describes a purchase that occurred on March 2nd 2011 for a Web-based article called "PaySwarm in Practice". The article was authored and listed for sale by Bob Smith and a personal use license was acquired by Jane, who may now peruse the article.
{
"@context": "http://purl.org/payswarm/v1",
"@id": "http://payswarm.example.com/contracts/28394729347",
"@type": ["ps:Transaction", "ps:Contract"],
"com:amount": "0.05",
"com:currency": "USD",
"dc:created": "2011-03-02T03:00:53Z",
"com:payee":
[
{
"@type": "com:Payee",
"com:currency": "USD",
"com:destination": "https://payswarm.example.com/i/authority/accounts/main",
"com:payeePosition": 0,
"com:rate": "10.00",
"com:rateContext": "com:TaxExempt",
"com:rateType": "com:InclusivePercentage",
"rdfs:comment": "authority Transaction Processing"
}
],
"com:transfer":
[
{
"@type": "com:Transfer",
"com:amount": "0.045",
"com:currency": "USD",
"com:destination": "https://payswarm.example.com/i/bob/accounts/primary",
"com:forTransaction": "http://payswarm.example.com/contracts/28394729347",
"com:source": "https://payswarm.example.com/i/jane/accounts/primary",
"rdfs:comment": "Payment for PaySwarm in Practice by Bob Smith."
},
{
"@type": "com:Transfer",
"com:amount": "0.005",
"com:currency": "USD",
"com:destination": "https://payswarm.example.com/i/authority/accounts/main",
"com:forTransaction": "http://payswarm.example.com/contracts/28394729347",
"com:source": "https://payswarm.example.com/i/jane/accounts/primary",
"rdfs:comment": "authority Transaction Processing"
}
],
"dc:created": "2011-03-02T03:00:53Z",
"ps:asset":
{
"@id": "http://example.com/articles/1#asset",
"@type": ["ps:Asset", "ps:WebPage"],
"dc:creator":
{
"foaf:name": "Bob Smith"
},
"dc:title": "PaySwarm in Practice",
"ps:assetProvider": "https://payswarm.example.com/i/bob",
"ps:authority": "https://payswarm.example.com/client-config",
"ps:contentUrl": "http://example.com/articles/1",
"sec:signature":
{
"@type": "ps:JsonLdSignature",
"dc:created": "2011-03-02T00:00:00Z",
"dc:creator": "https://payswarm.example.com/i/bob/keys/4",
"sec:signatureValue": "XuLEGuq+ne56Qsc5Nic8I="
}
},
"ps:assetAcquirer": "https://payswarm.example.com/i/jane",
"ps:assetProviderIdentity":
{
"ps:identityHash": "df913752be56fe0d37dcedc2d7f44708373d2a68"
},
"ps:license":
{
"@id": "http://payswarm.example.com/licenses/blogging",
"@type": "ps:License",
"dc:format": "text/html",
"ps:licenseTemplate": "Personal Use License ..."
},
"ps:listing":
{
"@id": "http://example.com/articles/1#listing",
"@type": ["gr:Offering", "ps:Listing"],
"com:payee":
[
{
"@id": "http://example.com/articles/1#listing-payee",
"@type": "com:Payee",
"com:currency": "USD",
"com:destination": "https://payswarm.example.com/i/bob/accounts/primary",
"com:rate": "0.05",
"com:rateType": "com:FlatAmount",
"rdfs:comment": "Payment for PaySwarm in Practice by Digital Bazaar."
}
],
"com:payeeRule":
[
{
"@type": "com:PayeeRule",
"com:destinationOwnerType": "ps:Authority",
"com:maximumRate": "10",
"com:rateType": "com:InclusivePercentage"
}
],
"ps:asset": "http://example.com/articles/1#asset",
"ps:assetHash": "14618b56ff597a2fed560db9aa0610fe442106a4",
"ps:license": "http://payswarm.example.com/licenses/blogging",
"ps:licenseHash": "0d8866836917f8ef58af44accb6efab9a10610ad",
"sec:signature":
{
"@type": "ps:JsonLdSignature",
"dc:created": "2011-03-02T00:00:00Z",
"dc:creator": "https://payswarm.example.com/i/bob/keys/4",
"sec:signatureValue": "KXtwA5kXZBJzj1rkPMJmGDROjM+fpi2cJIB+Xqf10="
},
"ps:validFrom": "2011-03-02T00:00:00+0000",
"ps:validUntil": "2011-03-03T00:00:00+0000"
},
"ps:listingHash": "1acbd23c3a7d8827270a959a2760f7c4ded98022",
"sec:signature":
{
"@type": "ps:JsonLdSignature",
"dc:created": "2011-03-02T03:00:53Z",
"dc:creator": "https://payswarm.example.com/i/authority/keys/1",
"sec:signatureValue": "ZnGaAs0QCIfEAvCsj2TxRTs8ekQrbbQUXvTLWcQ0kQ=="
}
}
The decentralized settlement process is used to ensure the immediate and
smooth transition of funds from an account on one
The following terminology is used to describe concepts used to perform the
settling of accounts between multiple
The following algorithm ensures that funds transferred as a part of a
ps:TransactionBackhaul service from each
One of the freedoms that is ensured by this specification is the freedom to
own your data and move it to an
In order to ensure data portability from one
Once the transfer is complete, the new
The following terminology is used to describe concepts used to transfer all
accounts from an old
The following algorithm ensures that all
token.
@id values for all
ps:Identity@id, @type, foaf:name,
rdfs:label, vcard:adr
com:Account@id, @type, rdfs:label,
rdfs:comment,
com:amount, com:currency, ps:owner
sec:Key@id, @type, rdfs:label,
rdfs:comment, sec:publicKeyPem,
ps:owner
ps:Transactionrdfs:seeAlso) set to the newly generate IRI for the object.
The URL MUST include the token.
rdfs:seeAlso
value to setup HTTP 301 response codes for all migrated
A
The following terminology is used to describe concepts used when processing
The following algorithm describes the
This section still needs a ton of work: specify the JSON-LD messages that are transmitted in detail, examples, and cover error conditions and exceptions.
ps:constraintcom:minimumAmountcom:currencyps:Contract and ps:Receipt are generated as
specified in the algorithm, but funds MUST NOT be disbursed at that time.
Instead of the ps:Receipt's ps:contract's property
being of @type ps:Contract, it MUST instead be of type
ps:TransactionIntent. All other fields must remain the same both
in the short-form contract and the long-form contract.
The ps:TransactionIntent is
sent to the ps:TransactionIntent's for the parameterized ps:validUntil date in the
com:minimumAmount in the
ps:constraint property in the com:minimumAmount
in the ps:constraint property in the ps:TransactionIntents
for the parameterized com:source
com:destination in each ps:TransactionIntents, the
source ps:TransactionIntents intended
for the mode and the
value is query. Each ps:TransactionIntent on hold. It does
this by contacting each ps:TransactionIntent's intended
for the mode and the
value is hold. Each ps:TransactionIntents. It does
this by contacting each ps:TransactionIntent's intended
for the mode and the
value is finalize. Each ps:TransactionIntent and disburses the funds according to the
Decentralized Settlement Algorithm.
ps:TransactionIntents submitted before the
ps:validUntil date are automatically processed according to the
previous step.