I have entered my credit card information hundreds of times on the internet. The same credit card. I’m tired of pulling out my wallet every time I buy something so here’s a plea to the eCommerce world: please stop making me.
In this article, I’m going to make the case for allowing alternative payments with Ethereum and Metamask for no cost to your business except the time to set it up. You should hear me out because payment processing shouldn’t cost you a dime and I’m sure it is currently costing you many.
My last article was about logging into any website without passwords using Ethereum and Metamask — I suggest you read that one first. Note that while this article focuses on eCommerce, you can stick these payment buttons on any website (perhaps a tip box for your art blog?) and they will only be seen by Metamask users. Your mainstream audience won’t notice a difference.
This shouldn’t be a surprise to anyone, but payment processors are businesses that exist to make money. Here are some reasons to not like them:
Too bad you have to use them because there isn’t an alternative. Oh wait, there is!
Just like any other cryptocurrency, Ethereum can be used as a medium of exchange with no central authority, settlement in seconds, no chargebacks, and 0% fees for the party receiving payment. Ethereum can actually do much more than be a medium of exchange, but that’s a topic for another day.
Okay I hope you’re interested. Let’s write some code.
You can follow along in this repo, where I have built a simple checkout component.
Remember Metamask? We’re going to set up a webpage displaying a super secret checkout that only users with a Metamask plugin will see. Again, this is because Metamask injects web3 into your browser. Everyone else will continue seeing your normal website, none the wiser that you have become hip to web 3.0.
render(){if (web3){return (<metamaskCheckout/>);} else {return (<checkout/>);};}
All we’re doing so far is rendering a metamaskCheckout component if we detect web3 in the browser. If not, we render the regular checkout, which looks like this:
As I mentioned in my previous article, an Ethereum address can be used as a sort of username. Whenever the user signs a transaction of any kind, they are proving ownership of that address. This will come in handy later.
components/MetaPay.jsx
let { pay } = this.props;return (<Row><Col md={4}></Col><Col md={4}><center><h2>Checkout</h2><h5>Horray! You're a Metamask user.</h5><p>We'll give you the good stuff.</p><div><form><br/><FormGroup><FormControl type="text" value={pay.name} onChange={this.updateName.bind(this)}/>Name<FormControl type="text" value={pay.address} onChange={this.updateAddress.bind(this)}/>Address<FormControl type="text" value={pay.city} onChange={this.updateCity.bind(this)}/>City<FormControl type="text" value={pay.country} onChange={this.updateCountry.bind(this)}/>Country</FormGroup></form><br/><Button bsStyle="primary" bsSize="large" onClick={this.sendTxn.bind(this)}>Pay ${this.props.pay.usd_amt}</Button></div></center></Col></Row>);
This component will render a form asking for the user’s physical address (this can be pre-filled via this.props if the user has shopped with you before — bonus feature!).
When the user clicks this pay button, it formats an Ethereum transaction and sends that to Metamask for the user to sign in their browser. The amount of ether to send will be based on the spot price of ether at the time (e.g. if ether is $50 and the product is $20, the transaction would read 0.4 ETH). Here’s what it looks like for the user:
Of course if the user doesn’t have enough ether, they won’t be able to pay you. ¯\_(ツ)_/¯
They can buy ether though…
…with a credit card (oh, the irony).
Anyway, note that the user pays a flat transaction fee of 1–10 cents to send ether and you pay nothing to receive it. You can find out why the user pays a fee here if you’re interested.
actions/metaPay.js
sendTxn(web3, ether, nonce) {return (dispatch) => {let user = web3.eth.accounts[0];let wei = ether * Math.pow(10, 18);let gasPrice = 3 * Math.pow(10, 9);let gasLimit = 30000;let rawTx = {nonce: `0x${nonce.toString(16)}`,gasPrice: `0x${gasPrice.toString(16)}`,gasLimit: `0x${gasLimit.toString(16)}`,from: user,to: this.owner_address,value: `0x${wei.toString(16)}`};web3.eth.sendTransaction(rawTx, (err, txHash) => {if (err) { console.log('Error sending txn:', err); }// Save the transaction hashyourAPI.saveOrder(rawTx, txHash);})}}
Once the user signs the transaction, a callback is invoked that takes the transaction hash and stores it in your database for later use. It also stores the street address so the user doesn’t need to fill anything in next time.
At this point, the user is done! No billing address. No credit card info. Just one click of the “Accept” button.
It’s probably worth noting that while chargebacks are not possible, you do need to make sure the transaction actually made it into the Ethereum blockchain. This usually takes 10–30 seconds, but I think a nice process would be to simply check before printing a shipping label (usually done minutes to hours later).
To get a transaction by its hash, you can use the Etherscan API (or, if you want to be a good Ethereum citizen, run your own node). Maybe I’ll cover more on how to interact with Ethereum in a later article — I don’t want to lose too many readers over it yet. Feel free to ping me if you’re implementing this and get stuck.
admin/shipping.jsx
function printMetamaskShippingLabel(order_id) {// Get the order info related to this transaction from your systemvar order = api.getOrder(order_id);// Make sure the transaction is on the blockchain and is legitvar on_chain_order = api.getMinedOrder(order.txHash);if (!order || order.value != on_chain_order.value) {return (<txNotMinedComponent>);} else {// Record that you printed the shipping labelapi.logShipment(data);// Show screen that can be printedreturn (<div>format your shipping label here...</div>);}}
function render() {var id = this.props.order_id;var metamask_order = this.props.metamask_order;if (metmamask_order) {return printMetamaskShippingLabel(id);} else {return printShippingLabel(id);};}
This component is seen by whomever is preparing the shipment. To prevent any fraud, your shipper will see a warning if the transaction isn’t mined yet or if it sent the wrong amount of ether (remember, your system logged the correct amount before). Otherwise, the shipping details are displayed as they normally would be.
At this point, you can be 100% sure you got paid and you can display the label, print it, and ship your product. And the best part? No middleman cut into your profits.
That’s a fair question. You may have noticed that you aren’t getting paid any dollars — you’re getting paid in ether. You may also know that cryptocurrencies are notoriously volatile.
While I personally would recommend taking your payments in ether (See: historical ether price) I understand that everyone’s risk tolerance is different.
This is why companies exist that allow you to accept cryptocurrencies and get paid in dollars. Unfortunately, those companies also charge high fees and there’s really no reason to use them unless they bring in lots of new customers. But remember, I told you this would be free.
It turns out you don’t actually need to use one of those services. You can do this yourself for very little work and almost no cost. And that’s the topic of my next article. Stay tuned!
—
If you enjoyed this article, follow me on Twitter or come join the community at https://reddit.com/r/ethereum. You should also check out my company, ConsenSys, because we do awesome stuff.
Also, if you implement anything I’ve been talking about, tweet at me and I’ll let the community know.
—
P.S. While you’re waiting for my next article, I suggest getting your Metamask plugin at metamask.io and heading over to etherplay.io for some arcade games. No sign up is required and if you beat the high score, you make money! And in case you’re wondering, I don’t work on either of these products.
“Pay With Metamask” image credit to Vlad Todirut