pay wall
TRANSCRIPT
-
7/24/2019 Pay Wall
1/12
coinbaseThe Coinbase API for Node.js
The ocial Node.js library for the Coinbase API.
Features Full Test coverage.
Support for both API ey ! Secretand "Auth #authentication.
Convenient $ethods for $a%ing calls to the API.
Auto$atic parsing of API responses into relevant &avascript objects.
Adheres to the nodejs error'(rst callbac% protocol.
Continuous Integration testing against node ).*)+ ).**+ and ).*#.
Installationnp$ install coinbase
Version CompatibilityVersion GitHub repository*.)., This repository).*., $ateodelnorte-coinbase
Np$ coinbase pac%age na$e used to refer to the unocial coinbaselibrary
$aintained by att /alters. att graciously allo0ed us to use the na$e forthis pac%age instead. 1ou can still (nd that pac%age on 2ithub. Than%s+ att.
Quick StartThe (rst thing you3ll need to do is sign up for coinbase.
API Key + SecretIf you3re 0riting code for your o0n Coinbase account+ enable an API %ey. Ne,t+
create a Client object for interacting 0ith the API4
varClient =re5uire63coinbase37.Client8varclient =newClient693apiey3$y%ey+ 3apiSecret3$ysecret:78
!Aut"#If you3re 0riting code that 0ill act on behalf of another user+ start by creating a
ne0 "Auth # application. 1ou 0ill need to do so$e 0or% to obtain "Auth
credentials for your users8 0hile outside the scope of this docu$ent+ please
refer to our "Auth # tutorialand docu$entation. "nce you have these
credentials+ create a client4
varClient =re5uire63coinbase37.Client8
varclient =newClient69
https://www.npmjs.com/package/coinbasehttps://developers.coinbase.com/apihttps://www.npmjs.com/package/coinbase#featureshttps://coinbase.com/docs/api/authentication#hmachttps://coinbase.com/docs/api/authentication#oauth2https://www.npmjs.com/package/coinbase#installationhttps://www.npmjs.com/package/coinbase#version-compatibilityhttps://github.com/mateodelnorte/coinbasehttps://github.com/mateodelnorte/coinbasehttps://github.com/mateodelnortehttps://github.com/mateodelnorte/coinbasehttps://www.npmjs.com/package/coinbase#quick-starthttps://coinbase.com/https://www.npmjs.com/package/coinbase#api-key-secrethttps://coinbase.com/settings/apihttps://www.npmjs.com/package/coinbase#oauth2https://coinbase.com/oauth/applicationshttps://coinbase.com/oauth/applicationshttps://www.coinbase.com/docs/api/oauth_tutorialhttps://www.coinbase.com/docs/api/authentication#oauth2https://developers.coinbase.com/apihttps://www.npmjs.com/package/coinbase#featureshttps://coinbase.com/docs/api/authentication#hmachttps://coinbase.com/docs/api/authentication#oauth2https://www.npmjs.com/package/coinbase#installationhttps://www.npmjs.com/package/coinbase#version-compatibilityhttps://github.com/mateodelnorte/coinbasehttps://github.com/mateodelnorte/coinbasehttps://github.com/mateodelnortehttps://github.com/mateodelnorte/coinbasehttps://www.npmjs.com/package/coinbase#quick-starthttps://coinbase.com/https://www.npmjs.com/package/coinbase#api-key-secrethttps://coinbase.com/settings/apihttps://www.npmjs.com/package/coinbase#oauth2https://coinbase.com/oauth/applicationshttps://coinbase.com/oauth/applicationshttps://www.coinbase.com/docs/api/oauth_tutorialhttps://www.coinbase.com/docs/api/authentication#oauth2https://www.npmjs.com/package/coinbase -
7/24/2019 Pay Wall
2/12
-
7/24/2019 Pay Wall
3/12
:78
Sending bitcoin
varargs =9
DtoDDuser*Ee,a$ple.co$D+
Da$ountDD*.#GD+
DnotesDDSa$ple transaction for youD
:8
account.sendoney6args+ function6err+ t,n7 9
console.log63$y t,n id is4 3+t,n.id78
:78
;e5uesting bitcoin
varargs =9 Dfro$DDuser*Ee,a$ple.co$D+
Da$ountDD*.#GD+
DnotesDDSa$ple transaction for youD
:8
account.re5uestoney6args+ function6err+ t,n7 9
console.log63$y t,n id is4 3+t,n.id78
:78
=isting current transactions
account.getTransactions6null+ null+ function6err+ t,ns7 9
t,ns.foruyPrice6935ty3*))+ 3currency33SB3:+ function6err+ obj7 9
console.log63total a$ount4 3+obj.total.a$ount78
:78
&rror Han'lin%
-
7/24/2019 Pay Wall
4/12
(ype )escription
InvalidAccessTo%enreturned 0hen the current access to%en is no longervalid
-
7/24/2019 Pay Wall
5/12
np$ install
np$ test
1ou can also run the tests against various node environ$ents using the
Boc%er(le.e,a$ple (le.
1. cp Boc%er(le.e,a$ple Boc%er(le
#. edit Boc%er(le and unco$$ent the node version that interests you
3. KsudoL doc%er build 't coinbase'node .
4. KsudoL doc%er run 'it coinbase'node
$ore )ocumentation1ou can generate ht$l docu$entation by running the co$$and4
np$ install MM np$ run docs
"pen generated ht$l (les in docs- dir 0ith a bro0ser.
Making Bitcoin Paywall MiddlewareToday's comicdoesn't include a lot of built-in technology like Wednesday's did. Just a moth joke.
r was that just a mistake! "'m not sure. Mo#ing on...
Wednesday's comic had a Bitcoin $aywall% and in Wednesday's blog " e&$lained how "
$rocessed a () res$onse in the client to make it work. But the ser#er $layed more than a bit
$art in the whole o$eration. *et it! Bit $art. Bitcoin. Mo#ing on...
It's like regular money, but with more math.
To handle the Bitcoin $ayments and unlock the content% there are se#eral $ieces at work. " am
using the +&$ress frameworkfor my web a$$lication% so " ha#e a middleware a$$lied to each
non-free resource. There is also a Bitcoin address generator to create new $ayment addresses.
,nother resource ser#es as the $ayment notification - when $ayment is made to an address% thisresource recei#es data about the transaction. inally% there is a datastore that manages the
records to kee$ all the other $ieces in sync.
This is how it works
irst% a resource is re/uested which re/uires $ayment. The middleware checks with
the datastore to see if the re/uesting client has an e&isting record for this resource.
"f no e&isting record is found% it means the client has ne#er attem$ted to access thisresource before. The middleware uses the address generator to create a new
$ayment address record and gi#es it to the datastore. The client is returned the ()
https://www.npmjs.com/package/coinbase#more-documentationhttp://amphibian.com/170http://expressjs.com/http://3.bp.blogspot.com/-CK-HBX-7SuI/VV5-eHe3sEI/AAAAAAAABgA/IYloBWJeuME/s1600/bitcoin_logo2.pnghttps://www.npmjs.com/package/coinbase#more-documentationhttp://amphibian.com/170http://expressjs.com/ -
7/24/2019 Pay Wall
6/12
res$onse along with the s$ecial $ayment instruction headers.
,lternati#ely% the datastore might find a record for this resource and client. That
means the client has been here before. The record returned by the datastore will
indicate whether or not the $ayment is com$lete. "f the $ayment has been made% the
middleware allows normal access. "f $ayment has not been made% the middleware
returns the () res$onse to the client with the s$ecial $ayment instruction headers.
The data for those headers comes out of the $ayment record.
,t any time% an e&ternal Bitcoin $rocessing system can determine that $ayment has
been made to one of the addresses generated by the address generator. "t sends
data on the $ayment transaction to the $ayment callback resource which looks u$ the
record in the datastore and marks it as $aid.
" used the 0oinbase Merchant ,P"as the e&ternal Bitcoin $rocessing system. When " create
addresses with 0oinbase% " can s$ecify a callback 123 for each one and 0oinbase will P4T
some data to it when $ayment is made. +ach address gets a uni/ue 123 so my system can look
u$ the $ayment record that matches it. " am using the official 0oinbase 5ode modulein my a$$.
6ere is a basic outline of the a$$
,are,press re5uire6De,pressD78,arapp e,press678-- $oc% purchase record,arde$o;ecord 9 recordId4 D*#GOD+ code4 Dproduct'codeD+ paid4 *alse+ cost4 *#.GO+ address4 DbitcoinaddressD+ secret4 DitsasecretD
:8-- $oc% datastore object,ardatastore 9 (nd;ecord4 *unction6re5+ productCode+ callbac%7 9 callbac%6D*#GOD78 :+ chec%PaidStatus4 *unction6recordId+ callbac%7 9 callbac%6de$o;ecord78 :+ ne0;ecord4 *unction6data7 9
-- store the record :+ (nd;ecord>ySecret4 *unction6secret+ callbac%7 9
https://developers.coinbase.com/docs/merchantshttps://www.npmjs.com/package/coinbasehttps://developers.coinbase.com/docs/merchantshttps://www.npmjs.com/package/coinbase -
7/24/2019 Pay Wall
7/12
i*6secret de$o;ecord.secret7 9 callbac%6de$o;ecord78 : else9 callbac%6null78 : :
:8*unctionne0>itcoinAddress6productCode+ callbac%7 9 callbac%6null+ de$o;ecord78:*unctionsendG)#6res+ data7 9
res.seteader6DQ'Pay$ent'Types'AcceptedD+ D>itcoinD78 res.seteader6DQ'Pay$ent'Address'>itcoinD+ data.address78 res.seteader6DQ'Pay$ent'A$ount'>itcoinD+ data.cost78
res.sendStatus6G)#78:*unctionpay0alliddle0are6re5+ res+ ne,t7 9
-- let3s use the ;= as the product code+ -- since that3s really 0hat is being sold ,arproductCode re5.path8
datastore.(nd;ecord6re5+ productCode+ *unction6recordId7 9
i*6recordId7 9
-- found a record+ 0hich $eans that this client
-- has a pay$ent address and purchase record already. -- no0 chec% to see if it has been paid. datastore.chec%PaidStatus6recordId+ *unction6data7 9
i*6data.paid7 9
ne,t678 -- all paid+ $ove along...: else9
-- respond 0ith the pay$ent address that already e,ists
sendG)#6res+ data78
:
:78
: else9
-- no record found+ 0hich $eans a ne0 >itcoin
-
7/24/2019 Pay Wall
8/12
-- address and purchase record $ust be created.
ne0>itcoinAddress6productCode+ *unction6err+ data7 9
i*6err7 9
ne,t6err78
: else9
datastore.ne0;ecord6data78 sendG)#6res+ data78
:
:78
:
:78:app.get6D-freeD+ *unction6re5+ res+ ne,t7 9 res.send6Dfree contentD78:78app.get6D-paidD+ pay0alliddle0are+ *unction6re5+ res+ ne,t7 9 res.send6Dpaid contentD78:78app.get6D-callbac%D+ *unction6re5+ res+ ne,t7 9
,arsecretCode re5.5uery.secret8 datastore.(nd;ecord>ySecret6secretCode+ *unction6record7 9 i*6record7 9 record.paid true8 : :78 res.sendStatus6#))78
:78-- '''''''''''' start listening,arserver app.listen6)))+ *unction67 9 console.log6Dlistening on port RdD+ server.address67.port78:78
That looks like a lot of code% but it's not really that com$licated. 5ear the to$% you see " ha#e
some mock objects for the demo. "n a real scenario% your datastore object would access an
27BM4 or the file system to store and retrie#e actual $urchase records. 6ere% though% a single
fake record and some stub functions will suffice. The newBitcoin,ddressfunction is also a stub -
in the real a$$% this is where " use the 0oinbase ,P" to create addresses and associated
$urchase records each with their own uni/ue secret code as $art of the callback 123. That
-
7/24/2019 Pay Wall
9/12
secret code should ne#er be returned to the user% but needs to be stored so the record can be
retrie#ed later in the callback handler. The send'()function is just a utility function that sets the
s$ecial res$onse headers and sends the () code.
The $aywallMiddleware function is the im$lementation of the algorithm " described abo#e. "t uses
the mock datastore and address generation function.
The routes at the bottom allow testing the system. 3aunch the a$$ and $oint your browser
tohtt$.88loc lhost.9(((8free
. :ou should get the free content. 5ow try
htt$.88 loc lhost.9(((8$ d
. :ou should get a () res$onse. This is because the 8$aidroute
includes the $aywallMiddleware. To get access% you'll need to $ay.
This demo doesn't re/uire any real Bitcoin transactions to take $lace. To simulate the callback
coming from 0oinbase% " included a8callbackroute that is a *+T% which makes it easy to test
from your browser. "n real life% this will be a P4T. To simulate sending $ayment to the address%
you just ha#e to go tohtt$.88loc lhost.9(((8c llb c !secret;its secret
. When you do% you
should get a sim$le < res$onse...but on the ser#er side% the demo record was u$dated to $aid
because the secret code matched. 5ow you can go back tohtt$.88loc lhost.9(((8$ id
and get
the $aid content. "f you had used a different =incorrect> #alue for secret% the8$aidresource would
not ha#e been unlocked.
5e&t week "'ll go into a little more detail about how " use the 0oinbase ,P". My ho$e is that
someday more content creators such as myself can use functions like this for micro$ayments in
$lace of running ad#ertisements on their sites.
But that's just a dream right now. 6ow long will it take to become reality! , few moths! " mean%
months!
1sing 6TTP () for a Bitcoin Paywall
Bitcoin. Perfect for Microtransactions?
The $unchline for today's comic is hidden behind a $aywall. "t is a literal wall% built by the frogs to
hide the last frame of the comic. 6owe#er% if you ha#e some Bitcoin to s$are =it costs (.((?
coins% about @(.)A 14 at the $resent time> you can actually $ay for the wall to be remo#ed.
, fair amount of interesting work went in to this comic% but it all re#ol#es around the conce$t of
http://3.bp.blogspot.com/-Er6OqxG8bDY/VVvlkJgD7aI/AAAAAAAABfQ/LtCV1G6wdXo/s1600/bitcoin_logo.png -
7/24/2019 Pay Wall
10/12
using the 6TTP () res$onse code.
2es$onse code () is officially reser#ed for future use but " felt that it was about time the future
showed u$. "t's )(?A. Where is my moon colony!! ,nyway% () means Payment 2e/uired and
was a$$arently intended to be a way for web ser#ers to indicate to clients that the re/uested
resource had to be $urchased. 1nfortunately% a way to $ay for those resources was ne#er
worked out and the res$onse code has languished in the realm of TB7 for many years.
But these days we ha#e ,ja&% 2+4T web ser#ices% and Bitcoin. "t's all coming together. Peo$le
ha#e kicked around the notion of integrating ()'s with Bitcoin transactions for a few years now
but no significant im$lementation has emerged. With today's comic% sadly% nothing has changed.
" did% howe#er% create a functional web content $aywall for Bitcoin microtransactions. 6ere's how
it works...
When a client - be it a human-o$erated web browser or another com$uter $rogram - accesses a
123 which does not dis$ense free content% the ser#er will return a () res$onse instead of the
content. That res$onse also includes three s$ecial headers% e&am$les of which are shown here
C-Payment-Ty$es-,cce$ted Bitcoin
C-Payment-,ddress-Bitcoin $utarealbitcoinaddresshere
C-Payment-,mount-Bitcoin ?.)9
The first% C-P yment-Ty$es-,cce$ted% should be a comma-se$arated list of acce$table
$ayment ty$es. "n my e&am$le and in my comic " am only acce$ting Bitcoin for now% although a
similar form of $ayment such as 3itecoin would easily be $ossible in $lace of or in addition to
Bitcoin. +ach item listed in this header should be used to check the other ) headers. TheC-
P yment-,ddress-CCCheader s$ecifies an address to which the $ayment should be sent. The
C-P yment-,mount-CCCheader s$ecifies how much this $articular resource costs.
The key is that the last $art of the address and amount headers should match an item in the list
of ty$es acce$ted. "f " wanted to acce$t either Bitcoin or 3itecoin% my headers might look like this
C-Payment-Ty$es-,cce$ted Bitcoin% 3itecoin
C-Payment-,ddress-Bitcoin $utarealbitcoinaddresshere
C-Payment-,mount-Bitcoin ?.)9
C-Payment-,ddress-3itecoin $utareallitecoinaddresshere
C-Payment-,mount-3itecoin ).9A
"t's then u$ to the client to deal with this res$onse. Today% browsers will silently ignore this e&tra
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.3http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.3 -
7/24/2019 Pay Wall
11/12
information and just tell you that the res$onse code means Payment 2e/uired without letting
you know how to $ay. "n the future% browsers might $rom$t you to submit the $ayment =see this
Dero 0lick Bitcoin Micro$ayments>. Today% though% you ha#e to do things manually.
"n certain cases% the ser#er could include the Bitcoin address and $rice in the 6TM3 that
accom$anies the () res$onse. 4ince " am just re/uesting the $aid resources #ia ,ja&% " didn't
bother with that and don't include anything human-readable in the res$onse. 6ere is how my
client-side code works when you #iew the comic
*unctionchec%ForPay$ent67 9
.aja,69 url4 D-paidContent-pay0all'co$icD+
dataType4 Dht$lD+ success4 *unction6data7 9
63co$icArea37.ht$l6data78
:+
error4 *unction6,hr+ respTe,t+ et7 9
i*6,hr.status G)#7 9
,araddr ,hr.get;esponseeader6DQ'Pay$ent'Address'
>itcoinD78 ,arcost ,hr.get;esponseeader6DQ'Pay$ent'A$ount'>itcoinD78
,arbc5r encode;ICo$ponent6Dbitcoin4D! addr ! DHa$ountD! cost78
i*66DpaydivD7.ht$l67 DD7 9 6DpaydivD7.ht$l6D?pPay 0ith >itcoinJ?brD! D?i$g src3-5rcHte,tD! bc5r !D3?brD!
DSend D! cost ! D >TC to?brD! addr ! D?-pD78 :
setTi$eout6chec%ForPay$ent+ #)))78
: else9
console.log6DfailedD78 :
:
:78
http://challengepost.com/software/zero-click-bitcoin-micropaymentshttp://challengepost.com/software/zero-click-bitcoin-micropayments -
7/24/2019 Pay Wall
12/12
:
When the free #ersion =missing the last frame> of the comic loads% checkorPayment=>is called
and attem$ts to get the data for the com$lete comic from the 123 /paidContent/paywall-comic.
,nything on my site with a $ath starting with/paidContent/will re/uire $urchasing. n a
successful res$onse% which you'll only get if you'#e $aid% the un$aid #ersion of the comic is
re$laced with the data from the ser#er.
The interesting $art is the error res$onse handling on line ??. , () res$onse is an error
because it is in the (( range - indicating a client-side error. "t's not a #ery serious error - just
asking for something for which you ha#e not $aidE " am using jFuery so the first $arameter
$assed to the error handler function is thej/C62 object. There are many things you can do with
that object% but " only need to check the res$onse status to see if it is a ()% and if so " read the
#alues of theC-P yment-,ddress-B tco n
andC-P yment-,mount-B tco n
headers. :es% "
am ignoring my ownC-P yment-Ty$es-,cce$ted
header because " ha$$en to know that it
only contains Bitcoin =that's the only kind of coin " ha#e right now>. "f " e&$ected other ty$es% the
right thing to do would be to read the C-Payment-Ty$es-,cce$tedheader and loo$ o#er the listof #alues to get the names of the other headers.
" take the address and $rice and submit them to my F2 0ode image generation 123to make an
easy% scannable way to $ay - but also just dis$lay the address and $rice to the user. ,gain% "'m
doing this on the client side because "'m re/uesting the data with ,ja&. "f the user na#igated
directly to a 123 which re/uired $ayment% the ser#er could ha#e res$onded with that 6TM3 as
$art of the () $age% much in the same way ser#ers res$ond with custom =and sometimes
hel$ful> ( $ages today.
The last $art is to check the /paidContent/paywall-comic123 again to see if a $ayment has gone
through. 4ince it can be a few seconds before 0oinbase tells my ser#er that $ayment has been
sent to the address% " took the /uick and dirty route of setting a timeout and running the
wholecheckorPayment=>function again. " could ha#e connected a Websocketto wait for
$ayment confirmation from the ser#er if " wanted to get fancy - a website that was e&$ected to
get more traffic than my comic would $robably want to go that route instead. , $ossible future
enhancement would be to include an additional header with a recommendation for the client -
s$ecifying if it should refresh% wait% redirect so some other 123% etc.
"n the future% " might $ut more s$ecial features on,m$hibian.comon the /paidContent/123%
instead of it just being $art of the joke. Maybe s$ecial comics that you can only access by $aying
a few cents! "'m not sure yet% but " tried to de#elo$ a framework that robust enough to su$$ort
future e&$ansion. ,t this $oint% " can easily make the ser#er re/uest $ayment for anything thanks
to the +&$ressmiddleware that " wrote combined with the 0oinbase 5ode module. But that's too
much for a single blog $ost so "'ll talk about that on ridayE
" also ho$e that more web sites ado$t and e&$and on this model now that " ha#e it working in a
semi-legitimate a$$lication. "n my o$inion% it beats dis$laying ads for enabling content creators to
monetiGe. :ou can hel$ me monetiGe by $aying to get the whole comic todayE
http://api.jquery.com/jQuery.ajax/#jqXHRhttp://thoughts.amphibian.com/2015/05/make-your-own-qr-codes-with-node.htmlhttp://thoughts.amphibian.com/2015/05/make-your-own-qr-codes-with-node.htmlhttp://thoughts.amphibian.com/2014/10/socketio-with-express.htmlhttp://thoughts.amphibian.com/2014/10/socketio-with-express.htmlhttp://amphibian.com/http://expressjs.com/https://www.npmjs.com/package/coinbasehttp://api.jquery.com/jQuery.ajax/#jqXHRhttp://thoughts.amphibian.com/2015/05/make-your-own-qr-codes-with-node.htmlhttp://thoughts.amphibian.com/2014/10/socketio-with-express.htmlhttp://amphibian.com/http://expressjs.com/https://www.npmjs.com/package/coinbase