HCNet.org maintains a communication server, which makes it easier to use the mapping and regulation servers to send and receive payments. When using the communication server, the only code you need to write is a private service to receive payment notifications and respond to regulatory checks from the communication and regulation servers.
When using the communication server, you send payments by making an HTTP POST request to it instead of a Aurora server. It doesn’t change a whole lot for simple transactions, but it will make the next steps of map and regulation much simpler.
The communication server requires a MySQL or PostgreSQL database in order to track and coordinate transaction and regulation information. Create an empty database named HCNet_communication and a user to manage it. You don’t need to add any tables; the communication server has a special command to do that for you.
Next, download the latest communication server for your platform. Install the executable anywhere you like. In the same directory, create a file named communication.cfg. This will store the configuration for the communication server. It should look something like:
Next, download the latest communication server for your platform. Install the executable anywhere you like. In the same directory, create a file named communication.cfg. This will store the configuration for the communication server. It should look something like:
Before starting the server the first time, the tables in your database need to be created. Running communication server with the --migrate-db argument will make sure everything is set to go:
./communication --migrate-db
Each time you update the communication server to a new version, you should run this command again. It will upgrade your database in case anything needs to be changed.
Now that your database is fully set up, you can start the communication server by running:
./communication
The communication server takes commands in the form of HTTP requests, so we can test submitting a payment by sending a POST request to /payments. Try sending 1 USD to the account
GRTBKZPYOQYPDEFJKLKY9FNNRQMGFLVHKBVCGNSLRRGSMPGF78GFDCVK5.
(Remember that the receiving account will need to trust the asset first. See issuing assets for more details.)
curl -X POST -d \
"id=unique_payment_id&\
amount=1&\
asset_code=USD&\
asset_issuer=GAPJN32J7O6EXXWNZ2P5VIMT7KFETQMZN27IILUSW7KZDZKCNRLQFON&\
destination=GAIGZHHWK3REZQPLQX5DNUN4A32CSEONTU6CMDBO7GDWLPSXZDSYA4BU&\
source=S6EXXWNZ7J7EXXWNZ2P5VIMT7KAPJNMZN27MTLUSW7KZW7KCN2P5VIM" \
http://localhost:8006/payment
var request = require('request');
request.post({
url: 'http://localhost:8006/payment',
form: {
id: 'unique_payment_id',
amount: '1',
asset_code: 'USD',
asset_issuer:
'GAPJN32J7O6EXXWNZ2P5VIMT7KFETQMZN27IILUSW7KZDZKCNRLQFON',
destination:
'GAIGZHHWK3REZQPLQX5DNUN4A32CSEONTU6CMDBO7GDWLPSXZDSYA4BU',
source:
'S6EXXWNZ7J7EXXWNZ2P5VIMT7KAPJNMZN27MTLUSW7KZW7KCN2P5VIM'
}
}, function(error, response, body) {
if (error || response.statusCode !== 200) {
console.error('ERROR!', error || body);
}
else {
console.log('SUCCESS!', body);
}
});
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import java.util.ArrayList;
import java.util.List;
public class PaymentRequest() {
public static void main(String [] args) {
HttpPost paymentRequest = new HttpPost("http://localhost:8006/payment");
List <NameValuePair> params = new ArrayList <NameValuePair>();
params.add(new BasicNameValuePair("id", "unique_payment_id"));
params.add(new BasicNameValuePair("amount", "1"));
params.add(new BasicNameValuePair("asset_code", "USD"));
params.add(new BasicNameValuePair("asset_issuer", "GAPJN32J7O6EXXWNZ2P5VIMT7KFETQMZN27IILUSW7KZDZKCNRLQFON"));
params.add(new BasicNameValuePair("destination", "GAIGZHHWK3REZQPLQX5DNUN4A32CSEONTU6CMDBO7GDWLPSXZDSYA4BU"));
params.add(new BasicNameValuePair("source", "S6EXXWNZ7J7EXXWNZ2P5VIMT7KAPJNMZN27MTLUSW7KZW7KCN2P5VIM"));
HttpResponse response = httpClient.execute(paymentRequest);
HttpEntity entity = response.getEntity();
if (entity != null) {
String body = EntityUtils.toString(entity);
System.out.println(body);
}
}
}
In the communication server configuration file, you might have noticed a callback URL named receive. Whenever a payment is received, the communication server will send an HTTP POST request to the URL you specified. The main responsibility of the receive endpoint is to update your customer’s balance in response to receiving a payment (since the payment went to your account on HC Net).
/**
* A small Express.js web server for handling payments from the communication server.
*/
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.urlencoded({ extended: false }));
app.post('/receive', function (request, response) {
var payment = request.body;
// `receive` may be called multiple times for the same payment, so check that
// you haven't already seen this payment ID.
if (getPaymentByIdFromDb(payment.id)) {
return response.status(200).end();
}
// Because we have one HC Net account representing many customers, the
// customer the payment is intended for should be in the transaction memo.
var customer = getAccountFromDb(payment.memo);
// You need to check the asset code and issuer to make sure it's an asset
// that you can accept payment to this account for. In this example, we just
// convert the amount to USD and adding the equivalent amount to the customer
// balance. You need to implement `convertToUsd()` yourself.
var dollarAmount = convertToUsd(
payment.amount, payment.asset_code, payment.asset_issuer);
addToBankAccountBalance(customer, dollarAmount);
response.status(200).end();
console.log('Added ' + dollarAmount + ' USD to account: ' + customer);
});
app.listen(8005, function () {
console.log('Communication server callbacks running on port 8005!');
});
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
/**
* A small Jersey web server for handling callbacks from HC Net services
*/
@Path("/")
public class HashcashCallbacks {
@POST
@Path("receive")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response receive(
@FormParam("id") String id,
@FormParam("amount") String amount,
@FormParam("asset_code") String assetCode,
@FormParam("asset_issuer") String assetIssuer,
@FormParam("memo") String memo) {
// `receive` may be called multiple times for the same payment, so check
// that you haven't already seen this payment ID. (getPaymentByIdFromDb is
// a method you’ll need to implement.)
if (getPaymentByIdFromDb(id)) {
return Response.ok().build();
}
// Because we have one HC Net account representing many customers, the
// customer the payment is intended for should be in the transaction memo.
// (getAccountFromDb is a method you’ll need to implement.) Customer customer = getAccountFromDb(memo);
// You need to check the asset code and issuer to make sure it's an asset
// that you can accept payment to this account for. In this example, we just
// convert the amount to USD and adding the equivalent amount to the
// customer balance. You need to implement `convertToUsd()` yourself.
Double dollarAmount = convertToUsd(amount, assetCode, assetIssuer);
addToBankAccountBalance(customer, dollarAmount);
return Response.ok().build();
System.out.println(String.format(
"Add %s, USD to account: %s",
dollarAmount,
customer));
}
}
Test Receive Callback
var HCNetSdk = require('HCNet-sdk');
HCNetSdk.Network.useTestNetwork()
var server = new HCNetSdk.Server('https://network.paybito.com/');
var sourceKeys = HCNetSdk.Keypair.fromSecret( 'S6EXXWNZ7J7EXXWNZ2P5VIMT7KAPJNMZN27MTLUSW7KZW7KCN2P5VIM');
var destinationId = 'GAIGZHHWK3REZQPLQX5DNUN4A32CSEONTU6CMDBO7GDWLPSXZDSYA4BU';
server.loadAccount(sourceKeys.publicKey())
.then(function(sourceAccount) {
var transaction = new HashcashSdk.TransactionBuilder(sourceAccount)
.addOperation(HCNetSdk.Operation.payment({
destination: destinationId,
asset: new HCNetSdk.Asset(
'USD', 'GAPJN32J7O6EXXWNZ2P5VIMT7KFETQMZN27IILUSW7KZDZKCNRLQFON'),
amount: '1'
}))
// Use the memo to indicate the customer this payment is intended for.
.addMemo(HCNetSdk.Memo.text('Amy'))
.build();
transaction.sign(sourceKeys);
return server.submitTransaction(transaction);
})
.then(function(result) {
console.log('Success! Results:', result);
})
.catch(function(error) {
console.error('Something went wrong!', error);
});
Server server = new Server("https://network.paybito.com/");
KeyPair source = KeyPair.fromSecretSeed( "S6EXXWNZ7J7EXXWNZ2P5VIMT7KAPJNMZN27MTLUSW7KZW7KCN2P5VIM");
KeyPair destination = KeyPair.fromAccountId(
"GAIGZHHWK3REZQPLQX5DNUN4A32CSEONTU6CMDBO7GDWLPSXZDSYA4BU");
Asset dollar = Asset.createNonNativeAsset("USD",
KeyPair.fromAccountId(
"GAPJN32J7O6EXXWNZ2P5VIMT7KFETQMZN27IILUSW7KZDZKCNRLQFON")
);
AccountResponse sourceAccount = server.accounts().account(source);
Transaction transaction = new Transaction.Builder(sourceAccount)
.addOperation(new PaymentOperation.Builder(destination, dollar, "1").build())
// Use the memo to indicate the customer this payment is intended for.
.addMemo(Memo.text("Amy"))
.build();
transaction.sign(source);
try {
SubmitTransactionResponse response = server.submitTransaction(transaction);
System.out.println("Success!");
System.out.println(response);
} catch (Exception e) {
System.out.println("Something went wrong!");
System.out.println(e.getMessage());
}
After running the above code, your callback server should have logged information about the payment.
Support Agent
*Powered by HashCash