Releases: payneteasy/hosted-fields-examples
Release list
v0.4.0
Example integrations of Hosted Fields: the same payment, one server per language.
hosted-fields-examples-go_*_linux_*.tar.gz— one static binary with the pages
embedded, plusdeploy/. Needs no runtime.hosted-fields-examples-go_*_darwin_arm64.tar.gz,
hosted-fields-examples-go_*_windows_amd64.zip— the same binary for trying the
example on a laptop. Nodeploy/: the systemd unit and the nginx snippet are for
a Linux server.hosted-fields-examples-nodejs-express-js_*.tar.gz— bundledserver.jswith
public/,views/anddeploy/. Needs Node 20+, nonode_modules.hosted-fields-examples-php.tar.gz— the sources withpublic/,views/and
deploy/. Needs PHP 8.4 with curl and openssl, no Composer:php -Sfor a look,
PHP-FPM behind nginx for anything else.hosted-fields-examples-python.tar.gz— the sources withtests/,public/,
views/anddeploy/. Needs Python 3.12+ and, unlike the others, a
pip install -r requirements.txtinto a venv on the target; then gunicorn.hosted-fields-examples-ruby.tar.gz— the sources withtest/,public/,
views/anddeploy/. Needs Ruby 3.1+ and abundle installon the target, then
puma. Note that macOS's system Ruby 2.6 will not run it.hosted-fields-examples-java.tar.gz— one jar with the pages inside it, plus
deploy/. Needs a JRE 21+ and nothing else:java -jar hosted-fields-example-java.jar.hosted-fields-examples-rust_linux_*.tar.gz— one binary with the pages compiled
in, plusdeploy/. Needs a glibc-based Linux and nothing else.hosted-fields-examples-rust_darwin_arm64.tar.gz,
hosted-fields-examples-rust_windows_amd64.zip— the same binary for trying the
example on a laptop. Nodeploy/: the systemd unit and the nginx snippet are for
a Linux server.hosted-fields-examples-nextjs.tar.gz— the standalone Next.js server with
public/,.next/anddeploy/. Needs Node 20+,node server.js. The URL
prefix is compiled in: rebuild from source to change it.
Settings and the RSA key are supplied through the environment, see the README.
What's Changed
Full Changelog: v0.3.0...v0.4.0
v0.3.0
Example integrations of Hosted Fields: the same payment, one server per language.
hosted-fields-examples-go_*_linux_*.tar.gz— one static binary with the pages
embedded, plusdeploy/. Needs no runtime.hosted-fields-examples-go_*_darwin_arm64.tar.gz,
hosted-fields-examples-go_*_windows_amd64.zip— the same binary for trying the
example on a laptop. Nodeploy/: the systemd unit and the nginx snippet are for
a Linux server.hosted-fields-examples-nodejs-express-js_*.tar.gz— bundledserver.jswith
public/,views/anddeploy/. Needs Node 20+, nonode_modules.hosted-fields-examples-php.tar.gz— the sources withpublic/,views/and
deploy/. Needs PHP 8.4 with curl and openssl, no Composer:php -Sfor a look,
PHP-FPM behind nginx for anything else.hosted-fields-examples-python.tar.gz— the sources withtests/,public/,
views/anddeploy/. Needs Python 3.12+ and, unlike the others, a
pip install -r requirements.txtinto a venv on the target; then gunicorn.hosted-fields-examples-ruby.tar.gz— the sources withtest/,public/,
views/anddeploy/. Needs Ruby 3.1+ and abundle installon the target, then
puma. Note that macOS's system Ruby 2.6 will not run it.hosted-fields-examples-java.tar.gz— one jar with the pages inside it, plus
deploy/. Needs a JRE 21+ and nothing else:java -jar hosted-fields-example-java.jar.hosted-fields-examples-nextjs.tar.gz— the standalone Next.js server with
public/,.next/anddeploy/. Needs Node 20+,node server.js. The URL
prefix is compiled in: rebuild from source to change it.
Settings and the RSA key are supplied through the environment, see the README.
What's Changed
Full Changelog: v0.2.0...v0.3.0
v0.2.0 — six languages, one payment
The same Hosted Fields payment, now written six times. v0.1.2 had one example; this release has
one per language, and the point of having more than one is that the interesting half — the card
iframes, the tokenization, the 3DS return — happens in the page, and the server behind it is
interchangeable.
| Server | Runs with | |
|---|---|---|
| Go | standard library only | one static binary, no runtime |
| Node.js | express only | Node 20+, no node_modules |
| PHP | no Composer at all | PHP 8.4+, php -S or PHP-FPM |
| Python | Flask + cryptography | Python 3.12+, python app.py or gunicorn |
| Ruby | Sinatra + puma | Ruby 3.1+, ruby app.rb or puma |
| Next.js | React 19, TypeScript | Node 20+, the page is a React tree |
What is new since v0.1.2
Four more examples. Next.js and React first, then PHP, Python on Flask and Ruby on Sinatra.
Each implements exactly the same seven routes and nothing else, and each documents the traps its
own language sets — PHP's $_POST renaming parameters, Python's urlopen raising on the 4xx that
carries a decline, Sinatra's http_origin protection rejecting the gateway's own 3DS callback.
The browser half lives once. shared/ is the source of truth for the stylesheet, the three
client scripts and the two pages, and scripts/sync-shared.sh copies it into every app. The
copies stay committed, so each directory still runs on its own with no pre-step, and CI fails a
copy that has drifted. Nothing in views/ is templated any more: the only thing any of these
servers generates is config.js, which is what lets the same HTML serve from all six.
Security work across every example. A Content-Security-Policy with no 'unsafe-inline',
naming the SDK origin in script-src, frame-src and connect-src; the 3DS return verified
twice over the same checksum, so a hand-edited URL gets a 403 instead of somebody else's order;
the POST /pay body filtered against a fixed list of eight customer_browser_* keys, so a caller
cannot choose what to charge; a CSPRNG client_orderid; loopback binding by default; and gateway
reply bodies kept out of the logs, which had been carrying the card's last four digits and the
holder's name.
An end-to-end suite. e2e-tests/ starts a fake gateway on one origin — both the API the
servers call and the SDK the browser loads — points every app at it through the environment, and
drives a real browser through the payment: the happy path, the SDK's field-state classes,
validation before tokenizing, a missing ticket, a refused Sale, a decline, the 3DS hop out to the
issuer and back through the signed callback, and forged signatures. Sixty tests, ten per app. The
OAuth signature is verified against a generated public key and the Sale's amount is checked
against the server's own, so a green run means the handshake works rather than that a page
rendered. It is local only — it needs every toolchain and a browser.
Which archive to take
Example integrations of Hosted Fields: the same payment, one server per language.
hosted-fields-examples-go_*_linux_*.tar.gz— one static binary with the pages
embedded, plusdeploy/. Needs no runtime.hosted-fields-examples-go_*_darwin_arm64.tar.gz,
hosted-fields-examples-go_*_windows_amd64.zip— the same binary for trying the
example on a laptop. Nodeploy/: the systemd unit and the nginx snippet are for
a Linux server.hosted-fields-examples-nodejs-express-js_*.tar.gz— bundledserver.jswith
public/,views/anddeploy/. Needs Node 20+, nonode_modules.hosted-fields-examples-php.tar.gz— the sources withpublic/,views/and
deploy/. Needs PHP 8.4 with curl and openssl, no Composer:php -Sfor a look,
PHP-FPM behind nginx for anything else.hosted-fields-examples-python.tar.gz— the sources withtests/,public/,
views/anddeploy/. Needs Python 3.12+ and, unlike the others, a
pip install -r requirements.txtinto a venv on the target; then gunicorn.hosted-fields-examples-ruby.tar.gz— the sources withtest/,public/,
views/anddeploy/. Needs Ruby 3.1+ and abundle installon the target, then
puma. Note that macOS's system Ruby 2.6 will not run it.hosted-fields-examples-nextjs.tar.gz— the standalone Next.js server with
public/,.next/anddeploy/. Needs Node 20+,node server.js. The URL
prefix is compiled in: rebuild from source to change it.
Settings and the RSA key are supplied through the environment, see the README.
What's Changed
- Add a Hosted Fields example on Next.js and React by @evsinev in #1
- Share the browser half from shared/, and drop templated views by @evsinev in #2
- Act on the review of eca9448: 3DS return, browser-field allowlist, and the rest by @evsinev in #3
- test: add a local e2e suite for all three examples by @evsinev in #4
- Add a PHP example by @evsinev in #5
- Add a Python (Flask) example by @evsinev in #6
- Add a Ruby (Sinatra) example by @evsinev in #7
New Contributors
Full Changelog: v0.1.2...v0.2.0
v0.1.2
Two merchant integrations of Hosted Fields — the same payment on a Go server and on a Node.js
one, with a browser half that is byte-for-byte identical between them.
See the README for screenshots and
a walk through the code.
Download
| Example | Platform | File |
|---|---|---|
| Go | Linux x86-64 | hosted-fields-examples-go_linux_amd64.tar.gz |
| Go | Linux arm64 | hosted-fields-examples-go_linux_arm64.tar.gz |
| Go | macOS Apple silicon | hosted-fields-examples-go_darwin_arm64.tar.gz |
| Go | Windows x64 | hosted-fields-examples-go_windows_amd64.zip |
| Node.js | any | hosted-fields-examples-nodejs-express-js.tar.gz |
The Go archives hold one static binary with the pages compiled in and need no runtime. The Node
archive holds a bundled server.js and needs Node 20+, but no npm install.
Verify with sha256sum -c SHA256SUMS.
The Linux archives also carry deploy/ with a systemd unit, an nginx snippet and an environment
template. The macOS and Windows builds do not: those are for trying the example on a laptop.
The macOS binary is not signed or notarised. Downloaded through a browser it arrives quarantined,
and Gatekeeper will refuse to start it until the attribute is cleared:
xattr -d com.apple.quarantine hosted-fields-examples-go
Running one
Every setting comes from the environment and none of them has a default: the app refuses to start
until the gateway URLs, the endpoint, the merchant login, the control key and the RSA private key
are all provided. See deploy/*.env.example in the Linux archive, and the README for what to ask
the gateway for.
Each app mounts everything under a URL prefix, so several of them fit behind one nginx.
Notes
- The RSA key signs the server calls and never leaves the server. It is not in this repository
and must not be committed. - Field validation messages the payer sees come from the SDK the gateway serves, not from this
code. To show them in a language of your own, switch onerror.coderather than printing
error.payerMessage.
Changes since v0.1.1
- Release archives no longer carry the version in their file name, so a link to
releases/latest/download/<name>keeps working across releases. The directory inside the
archive still names the version. - The README now opens with the two examples, screenshots of both screens, and a download table.
v0.1.1
The same two Hosted Fields examples as v0.1.0, now built for a laptop as well as a server.
What the examples show
Card number, expiry and CVV are iframes served by the payment gateway, so the card never reaches
the merchant server. Everything around them is the merchant's: the layout, the light and dark
themes, the result panel — and one of the merchant's own inputs, the cardholder name, sitting
between the gateway's fields in the same visual row. A redirect to a hosted payment page cannot
do that.
Both examples cover the whole flow: the single-use ephemeral ticket, tokenization, the Sale with
hosted_fields_token, status polling, and the 3DS return whose control checksum is verified
before the page renders. The browser half is byte-for-byte identical between the two.
Artefacts
| File | Contents | Requires |
|---|---|---|
hosted-fields-examples-go_v0.1.1_linux_amd64.tar.gz |
static binary with the pages compiled in, plus deploy/ |
nothing |
hosted-fields-examples-go_v0.1.1_linux_arm64.tar.gz |
the same, for arm64 | nothing |
hosted-fields-examples-go_v0.1.1_darwin_arm64.tar.gz |
the same, for Apple silicon | nothing |
hosted-fields-examples-go_v0.1.1_windows_amd64.zip |
the same, as .exe |
nothing |
hosted-fields-examples-nodejs-express-js_v0.1.1.tar.gz |
bundled server.js with public/, views/ and deploy/ |
Node 20+, no node_modules |
Verify with sha256sum -c SHA256SUMS.
The macOS and Windows builds carry no deploy/: the systemd unit and the nginx snippet are for a
Linux server, and these builds are for trying the example locally.
The macOS binary is not signed or notarised. Downloaded through a browser it arrives quarantined,
and Gatekeeper will refuse to start it until the attribute is cleared:
xattr -d com.apple.quarantine hosted-fields-examples-go
Running one
Every setting comes from the environment and none of them has a default: the app refuses to start
until the gateway URLs, the endpoint, the merchant login, the control key and the RSA private key
are all provided. See deploy/*.env.example in the Linux archive, and the README for what to ask
the gateway for.
Each app mounts everything under a URL prefix, so several of them fit behind one nginx.
Notes
- The RSA key signs the server calls and never leaves the server. It is not in this repository
and must not be committed. - Field validation messages the payer sees come from the SDK the gateway serves, not from this
code. To show them in a language of your own, switch onerror.coderather than printing
error.payerMessage.
Changes since v0.1.0
- Release binaries for Windows x64 and macOS arm64.
v0.1.0
First release of the two Hosted Fields integration examples: the same payment implemented on two
servers, with a browser half that is byte-for-byte identical between them.
What the examples show
Card number, expiry and CVV are iframes served by the payment gateway, so the card never reaches
the merchant server. Everything around them is the merchant's: the layout, the light and dark
themes, the result panel — and one of the merchant's own inputs, the cardholder name, sitting
between the gateway's fields in the same visual row. A redirect to a hosted payment page cannot
do that.
Both examples cover the whole flow: the single-use ephemeral ticket, tokenization, the Sale with
hosted_fields_token, status polling, and the 3DS return whose control checksum is verified
before the page renders.
Artefacts
| File | Contents | Requires |
|---|---|---|
hosted-fields-examples-go_v0.1.0_linux_amd64.tar.gz |
one static binary with the pages compiled in, plus deploy/ |
nothing |
hosted-fields-examples-go_v0.1.0_linux_arm64.tar.gz |
the same, for arm64 | nothing |
hosted-fields-examples-nodejs-express-js_v0.1.0.tar.gz |
bundled server.js with public/, views/ and deploy/ |
Node 20+, no node_modules |
Verify with sha256sum -c SHA256SUMS.
Running one
Every setting comes from the environment and none of them has a default: both apps refuse to
start until the gateway URLs, the endpoint, the merchant login, the control key and the RSA
private key are all provided. See deploy/*.env.example in either archive, and the README for
what to ask the gateway for.
Each app mounts everything under a URL prefix, so several of them fit behind one nginx; deploy/
carries the systemd unit and the nginx snippet.
Notes
- The RSA key signs the server calls and never leaves the server. It is not in this repository
and must not be committed. - Field validation messages the payer sees come from the SDK the gateway serves, not from this
code. To show them in a language of your own, switch onerror.coderather than printing
error.payerMessage.