Payment Handler Sample
There is a sample code in popular languages to implement payment handling.
- PHP
- Java
- C++
- JavaScript
$private_key = '8c29558bjiiiif354ccd22629207dd8';
$parameters = $_POST;
$signature = '';
unset($parameters['sign']);
ksort($parameters);
foreach ($parameters as $k => $v) {
$signature .= $k . '=' . $v;
}
$signature = hash('md5', $signature . $private_key);
if ($_POST['sign'] == $signature) {
// check if transaction_id was successful
$localTransaction = []; // get it from your database by $parameters['transaction_id']
if($localTransaction && $localTransaction['status'] == 'success'){
$result = [
'status' => 'success',
'transaction_id' => $localTransaction['id'],
];
echo json_encode($result);
exit;
}
// if $parameters['transaction_id'] is new - you'll need to try handle
// it in next steps
// your code here
$successfulGameCharge = true;
if ($successfulGameCharge) {
$result = [
'status' => 'success',
'transaction_id' => $localTransaction['id'],
];
} else {
$result = [
'status' => 'error',
'error_message' => 'Payment was not charged.',
];
}
} else {
$result = [
'status' => 'error',
'error_message' => 'Signature is incorrect.',
];
}
echo json_encode($result);
package com.xp101;
import javax.xml.bind.DatatypeConverter;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.stream.Collectors;
public class Main {
private final static String privateKey = "8c29558bjiiiif354ccd22629207dd8";
public static void main(String[] args) throws NoSuchAlgorithmException {
Map<String, String> params = convertToSortedKeyValuePair(args);
MessageDigest md = MessageDigest.getInstance("MD5");
String sign = params.get("sign");
params.remove("sign");
String signature = params.entrySet().stream().map(s -> String.join("=", s.getKey(), s.getValue())).collect(Collectors.joining());
md.update((signature + privateKey).getBytes(StandardCharsets.UTF_8));
signature = DatatypeConverter.printHexBinary(md.digest());
Map<String,String> result = new HashMap<>();
if (signature.equalsIgnoreCase(sign)) {
// check if transaction_id was successful
Map<String, String> localTransaction = new HashMap<>(); // get it from your database by params
if (!localTransaction.isEmpty() && "success".equals(localTransaction.get("status"))) {
result.put("status", "success");
result.put("transaction_id", localTransaction.get("id"));
System.out.println(createJsonString(result));
return;
}
// if params.get("transaction_id") is new - you'll need to try
// handle it in next steps
// your code here
boolean successfulGameCharge = true;
if (successfulGameCharge) {
result.put("status", "success");
result.put("transaction_id", localTransaction.get("id"));
} else {
result.put("status", "error");
result.put("error_message", "Payment was not charged.");
}
} else {
result.put("status", "error");
result.put("error_message", "Signature is incorrect.");
}
System.out.println(createJsonString(result));
}
private static Map<String, String> convertToSortedKeyValuePair(String[] args) {
Map<String, String> params = new TreeMap<>();
for (String arg: args) {
String[] splitFromEqual = arg.split("=");
String key = splitFromEqual[0];
String value = splitFromEqual[1];
params.put(key, value);
}
return params;
}
private static String createJsonString(Map<String, String> map) {
String jsonString = "{\n";
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
jsonString = jsonString + "\t\"" + entry.getKey() + "\": \"" + entry.getValue() + "\",\n";
}
int i = jsonString.lastIndexOf(",");
jsonString = jsonString.substring(0, i);
jsonString += "\n}";
return jsonString;
}
}
#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
#include "cryptopp/files.h"
#include "cryptopp/hex.h"
#include "cryptopp/md5.h"
#include "json.hpp"
#include <algorithm>
#include <iostream>
using namespace CryptoPP;
struct Transaction {
std::string status;
std::string id;
// ...
};
nlohmann::json payment_handler(const nlohmann::json ¶meters) {
nlohmann::json result = {};
nlohmann::json parameters_copy = parameters;
const std::string private_key = "8c29558bjiiiif354ccd22629207dd8";
const std::string sign = parameters_copy["sign"].get<std::string>();
parameters_copy.erase("sign");
std::string signature = "";
for (auto it = parameters_copy.begin(); it != parameters_copy.end(); ++it) {
signature += it.key() + "=" + it.value().get<std::string>();
}
signature += private_key;
Weak::MD5 hash;
std::string digest_hex;
std::string digest;
hash.Update((const byte *)&signature[0], signature.size());
digest_hex.resize(hash.DigestSize());
hash.Final((byte *)&digest_hex[0]);
HexEncoder encoder(new StringSink(digest));
StringSource(digest_hex, true, new Redirector(encoder));
std::for_each(digest.begin(), digest.end(),
[](char &c) { return c = std::tolower(c); });
if (sign == digest) {
// check if transaction_id was successful
const Transaction *local_transaction =
nullptr; // get it from your database by parameters->transaction_id
if (local_transaction && local_transaction->status == "success") {
result = {{"status", "success"},
{"transaction_id", local_transaction->id}};
}
// if parameters->transaction_id is new - you'll need to try handle
// it in next steps
// your code here
bool successful_game_charge = true;
if (successful_game_charge) {
result = {{"status", "success"},
{"transaction_id",
local_transaction ? local_transaction->id : "undefined"}};
} else {
result = {{"status", "error"},
{"error_message", "Payment was not charged."}};
}
} else {
result = {{"status", "error"},
{"error_message", "Signature is incorrect."}};
}
return result;
}
int main() {
// Parameters must be == POST parameters in real app
// nlohmann::json parameters = POST
nlohmann::json parameters = {
{"test7", "fasdf2"},
{"test3", "12355"},
{"test6", "gr312"},
{"test5", "fjd83"},
{"test9", "4ujd2"},
{"test2", "d8jfk5"},
{"test3", "12;3d"},
{"test8", "asdf84j"},
{"test10", "23ig8js"},
{"test4", "388ufj"},
{"transaction_id", "u8837hf"},
{"sign", "16bbea55c46505908bb5c303f1d6fa5a"}
};
nlohmann::json result = payment_handler(parameters);
}
// Node.JS version: >= 10
const md5Hash = require('crypto').createHash('md5');
const ksort = (obj) => {
const keys = Object.keys(obj).sort();
let sortedObj = {};
for (const i in keys) {
sortedObj[i] = obj[i];
}
return sortedObj;
}
const paymentHandler = (parameters) => {
const private_key = '8c29558bjiiiif354ccd22629207dd8';
const sign = parameters['sign'];
let signature = '';
let result = {};
delete parameters['sign'];
parameters = ksort(parameters);
for (const k of Object.keys(parameters)) {
signature += `${k}=${parameters[k]}`;
}
signature = md5Hash
.update(signature + private_key)
.digest('hex');
if (sign === signature) {
// check if transaction_id was successful
const localTransaction = {}; // get it from your database by parameters['transaction_id']
if (localTransaction && localTransaction['status'] === 'success') {
result = {
status: 'success',
transaction_id: localTransaction['id'],
};
}
// if parameters['transaction_id'] is new - you'll need to try handle
// it in next steps
// your code here
let successfulGameCharge = true;
if (successfulGameCharge) {
result = {
status: 'success',
transaction_id: localTransaction['id'],
};
} else {
result = {
status: 'error',
error_message: 'Payment was not charged.',
};
}
} else {
result = {
status: 'error',
error_message: 'Signature is incorrect.',
};
}
return result;
};
module.exports = paymentHandler;