Webhooks
Code samples to generate and verify signature hash for the data received via Payment Status webhooks sent from PortOne servers.
- Golang
- PHP
- NodeJS
- C#
- Java
- Python
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
)
type WebhookResponseObj struct {
Currency string
Amount string
OrderRef string
MerchantOrderRef string
CountryCode string
ChannelOrderRef string
Status string
ChannelKey string
MethodName string
Signature string
}
func VerifySignature(webhookResponseObj WebhookResponseObj, secretKey string) bool {
params := make(url.Values)
params.Add("currency", webhookResponseObj.Currency)
params.Add("amount", webhookResponseObj.Amount)
params.Add("order_ref", webhookResponseObj.OrderRef)
params.Add("merchant_order_ref", webhookResponseObj.MerchantOrderRef)
params.Add("channel_order_ref", webhookResponseObj.ChannelOrderRef)
params.Add("country_code", webhookResponseObj.CountryCode)
params.Add("status", webhookResponseObj.Status)
params.Add("channel_key", webhookResponseObj.ChannelKey)
params.Add("method_name", webhookResponseObj.MethodName)
data = params.Encode()
secret := []byte(secretKey)
message := []byte(data)
hash := hmac.New(sha256.New, secret)
hash.Write(message)
hash_value := base64.StdEncodin.EncodeToString(hash.Sum(nil))
// compare this hash_value to one received in payment response
if hash_value != webhookResponseObj.Signature {
println("Hash verification failed, not from valid source")
return false
} else {
println("Hash verification succeded")
return true
}
}
<?php
function VerifySignature($webhookResponseObj, $secretKey) {
$data = array(
'currency' =>$webhookResponseObj.Currency,
'amount' => $webhookResponseObj.Amount,
'order_ref' => $webhookResponseObj.OrderRef,
'merchant_order_ref' => $webhookResponseObj.MerchantOrderRef,
'channel_order_ref'=> $webhookResponseObj.ChannelOrderRef,
'country_code' => $webhookResponseObj.CountryCode,
'status' => $webhookResponseObj.Status,
'channel_key' => $webhookResponseObj.ChannelKey,
'method_name' => $webhookResponseObj.MethodName
);
ksort($data);
$message = http_build_query($data);
$hash_value = base64_encode(hash_hmac('sha256', $message, $secretKey, true));
if($hash_value !== responseObj.Signature){
echo "Hash verification failed, not from valid source";
return false;
} else{
echo "Hash verification succeded";
return true;
}
}
?>
var url = require('url');
var crypto = require('crypto');
function VerifySignature(webhookResponseObj, secretKey) {
const params = new URLSearchParams();
params.append('currency', webhookResponseObj.Currency)
params.append('amount', webhookResponseObj.Amount)
params.append('order_ref', webhookResponseObj.OrderRef)
params.append('merchant_order_ref', webhookResponseObj.MerchantOrderRef)
params.append('channel_order_ref', webhookResponseObj.ChannelOrderRef)
params.append('country_code', webhookResponseObj.CountryCode)
params.append('status', webhookResponseObj.Status)
params.append('channel_key', webhookResponseObj.ChannelKey)
params.append('method_name', webhookResponseObj.MethodName)
params.sort();
var message = params.toString()
var hash_value = crypto.createHmac('sha256', secretKey).update(message).hash.digest('base64');
if(hash_value !== webhookResponseObj.signature_hash){
console.log("Hash verification failed, not from valid source")
return false;
} else{
console.log("Hash verification succeded")
return true;
}
}
using System;
using System.Security.Cryptography;
using System.Collections.Specialized;
using System.Text;
using System.Web;
namespace Signature {
public class WebhookResponse {
public string Currency;
public string Amount;
public string OrderRef;
public string MerchantOrderRef;
public string CountryCode;
public string ChannelOrderRef;
public string Status;
public string ChannelKey;
public string MethodName;
public string Signature;
public WebhookResponse() {}
}
public class Signature {
public static bool VerifySignature(WebhookResponse webhookResponseObj, string secretKey) {
NameValueCollection parameters = new NameValueCollection();
// Sequence of params is important here
parameters.Add("amount", HttpUtility.UrlEncode(webhookResponseObj.Amount));
parameters.Add("channel_key", HttpUtility.UrlEncode(webhookResponseObj.ChannelKey));
parameters.Add("channel_order_ref", HttpUtility.UrlEncode(webhookResponseObj.ChannelOrderRef));
parameters.Add("country_code", HttpUtility.UrlEncode(webhookResponseObj.CountryCode));
parameters.Add("currency", HttpUtility.UrlEncode(webhookResponseObj.Currency));
parameters.Add("merchant_order_ref", HttpUtility.UrlEncode(webhookResponseObj.MerchantOrderRef));
parameters.Add("method_name", HttpUtility.UrlEncode(webhookResponseObj.MethodName));
parameters.Add("order_ref", HttpUtility.UrlEncode(webhookResponseObj.OrderRef));
parameters.Add("status", HttpUtility.UrlEncode(webhookResponseObj.Status));
string data = string.Join("&", Array.ConvertAll(parameters.AllKeys, key => $"{key}={parameters[key]}"));
Console.WriteLine("data: " + data);
byte[] secret = Encoding.UTF8.GetBytes(secretKey);
byte[] message = Encoding.UTF8.GetBytes(data);
using (HMACSHA256 hash = new HMACSHA256(secret))
{
byte[] hashValue = hash.ComputeHash(message);
string hashValueBase64 = Convert.ToBase64String(hashValue);
Console.WriteLine("hash_value: " + hashValueBase64);
if (hashValueBase64 != webhookResponseObj.Signature)
{
Console.WriteLine("Hash verification failed, not from valid source");
return false;
} else {
Console.WriteLine("Hash verification success");
return true;
}
}
return true;
}
public static void Main(string[] args) {
WebhookResponse wr = new WebhookResponse();
wr.Currency = "PHP";
wr.Amount = "7299.12";
wr.OrderRef = "2WsxnsRUq4evFG52utO6Yd7BGQf";
wr.MerchantOrderRef = "2WsxnGXFObnNXaiZZNf1dqWegFH_1";
wr.ChannelOrderRef = "6975352881716203803001";
wr.CountryCode = "PH";
wr.ChannelKey = "CYBERSOURCE_PH";
wr.MethodName = "Credit Card";
wr.Status = "Success";
wr.Signature = "8S/en9MtbZIAEdAORMxCDdjdos+vOTN+4JlQCQjp528=";
string Secret = "f993758ef2d10ae67ec8b2519c1df916aa2140d3a13d75e45e792adb03ca6e1a";
VerifySignature(wr, Secret);
}
}
}
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Map;
public class Main {
public static void main(String[] args) {
WebhookResponseObj webhookResponseObj = new WebhookResponseObj(
"THB", "100", "orderRefValue", "merchantOrderRefValue",
"US", "channelOrderRefValue", "success", "channelKeyValue",
"methodNameValue", "signatureValue"
);
boolean isValid = verifySignature(webhookResponseObj, "yourSecretKey");
System.out.println("Is signature valid? " + isValid);
}
public static boolean verifySignature(WebhookResponseObj webhookResponseObj, String secretKey) {
try {
StringBuilder data = new StringBuilder();
data.append("amount=").append(webhookResponseObj.getAmount())
.append("&channel_key=").append(webhookResponseObj.getChannelKey())
.append("&channel_order_ref=").append(webhookResponseObj.getChannelOrderRef())
.append("&country_code=").append(webhookResponseObj.getCountryCode())
.append("¤cy=").append(webhookResponseObj.getCurrency())
.append("&merchant_order_ref=").append(webhookResponseObj.getMerchantOrderRef())
.append("&method_name=").append(webhookResponseObj.getMethodName())
.append("&order_ref=").append(webhookResponseObj.getOrderRef())
.append("&status=").append(webhookResponseObj.getStatus());
byte[] secret = secretKey.getBytes();
byte[] message = data.toString().getBytes();
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(secret, "HmacSHA256");
sha256_HMAC.init(secretKeySpec);
byte[] hash = sha256_HMAC.doFinal(message);
String computedSignature = Base64.getEncoder().encodeToString(hash);
// Compare computed signature to the one received in webhook response
if (!computedSignature.equals(webhookResponseObj.getSignature())) {
System.out.println("Hash verification failed, not from a valid source");
return false;
} else {
System.out.println("Hash verification succeeded");
return true;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
class WebhookResponseObj {
private String currency;
private String amount;
private String orderRef;
private String merchantOrderRef;
private String countryCode;
private String channelOrderRef;
private String status;
private String channelKey;
private String methodName;
private String signature;
public WebhookResponseObj(String currency, String amount, String orderRef, String merchantOrderRef, String countryCode, String channelOrderRef, String status, String channelKey, String methodName, String signature) {
this.currency = currency;
this.amount = amount;
this.orderRef = orderRef;
this.merchantOrderRef = merchantOrderRef;
this.countryCode = countryCode;
this.channelOrderRef = channelOrderRef;
this.status = status;
this.channelKey = channelKey;
this.methodName = methodName;
this.signature = signature;
}
public String getCurrency() {
return currency;
}
public String getAmount() {
return amount;
}
public String getOrderRef() {
return orderRef;
}
public String getMerchantOrderRef() {
return merchantOrderRef;
}
public String getCountryCode() {
return countryCode;
}
public String getChannelOrderRef() {
return channelOrderRef;
}
public String getStatus() {
return status;
}
public String getChannelKey() {
return channelKey;
}
public String getMethodName() {
return methodName;
}
public String getSignature() {
return signature;
}
}
#!/usr/bin/python
# -*- coding: utf-8 -*-
import urllib
import hashlib
import hmac
import base64
class WebhookResponseObj:
def __init__(self, Currency, Amount, OrderRef, MerchantOrderRef, CountryCode, ChannelOrderRef, Status, ChannelKey, MethodName, Signature):
# Instance Variable
self.Currency = Currency
self.Amount = Amount
self.OrderRef = OrderRef
self.MerchantOrderRef = MerchantOrderRef
self.CountryCode = CountryCode
self.ChannelOrderRef = ChannelOrderRef
self.Status = Status
self.ChannelKey = ChannelKey
self.MethodName = MethodName
self.Signature = Signature
def GenerateSignature(WebhookResponseObj, secretKey):
f = {
'currency': WebhookResponseObj.Currency,
'amount': WebhookResponseObj.Amount,
'order_ref': WebhookResponseObj.OrderRef,
'merchant_order_ref': WebhookResponseObj.MerchantOrderRef,
'channel_order_ref': WebhookResponseObj.ChannelOrderRef,
'country_code': WebhookResponseObj.CountryCode,
'status': WebhookResponseObj.Status,
'channel_key': WebhookResponseObj.ChannelKey,
'method_name': WebhookResponseObj.MethodName,
}
message1 = urllib.urlencode(f)
message = bytes(message1).encode('utf-8')
secret = bytes(secretKey).encode('utf-8')
signature = base64.b64encode(hmac.new(secret, message, digestmod=hashlib.sha256).digest())
if (signature !== WebhookResponseObj.Signature) {
Print("Hash verification failed, not from valid source")
return false;
} else {
Print("Hash verification succeded")
return true;
}
Code samples to generate and verify signature hash for the data received via Payment Link Status webhooks sent from PortOne servers.
- Golang
- PHP
- NodeJS
- C#
- Java
- Python
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
)
type WebhookResponseObj struct {
Currency string
Amount string
LinkRef string
MerchantOrderRef string
CountryCode string
Status string
Signature string
}
func VerifySignature(webhookResponseObj WebhookResponseObj, secretKey string) bool {
params := make(url.Values)
params.Add("currency", webhookResponseObj.Currency)
params.Add("amount", webhookResponseObj.Amount)
params.Add("link_ref", webhookResponseObj.LinkRef)
params.Add("merchant_order_ref", webhookResponseObj.MerchantOrderRef)
params.Add("country_code", webhookResponseObj.CountryCode)
params.Add("status", webhookResponseObj.Status)
data = params.Encode()
secret := []byte(secretKey)
message := []byte(data)
hash := hmac.New(sha256.New, secret)
hash.Write(message)
hash_value := base64.StdEncodin.EncodeToString(hash.Sum(nil))
// compare this hash_value to one received in payment response
if hash_value != webhookResponseObj.Signature {
println("Hash verification failed, not from valid source")
return false
} else {
println("Hash verification succeded")
return true
}
}
<?php
function VerifySignature($webhookResponseObj, $secretKey) {
$data = array(
'currency' =>$webhookResponseObj.Currency,
'amount' => $webhookResponseObj.Amount,
'link_ref' => $webhookResponseObj.LinkRef,
'merchant_order_ref' => $webhookResponseObj.MerchantOrderRef,
'country_code' => $webhookResponseObj.CountryCode,
'status' => $webhookResponseObj.Status,
);
ksort($data);
$message = http_build_query($data);
$hash_value = base64_encode(hash_hmac('sha256', $message, $secretKey, true));
if($hash_value !== responseObj.Signature){
echo "Hash verification failed, not from valid source";
return false;
} else{
echo "Hash verification succeded";
return true;
}
}
?>
var url = require('url');
var crypto = require('crypto');
function VerifySignature(webhookResponseObj, secretKey) {
const params = new URLSearchParams();
params.append('currency', webhookResponseObj.Currency)
params.append('amount', webhookResponseObj.Amount)
params.append('link_ref', webhookResponseObj.LinkRef)
params.append('merchant_order_ref', webhookResponseObj.MerchantOrderRef)
params.append('country_code', webhookResponseObj.CountryCode)
params.append('status', webhookResponseObj.Status)
params.sort();
var message = params.toString()
var hash_value = crypto.createHmac('sha256', secretKey).update(message).hash.digest('base64');
if(hash_value !== webhookResponseObj.signature_hash){
console.log("Hash verification failed, not from valid source")
return false;
} else{
console.log("Hash verification succeded")
return true;
}
}
using System;
using System.Security.Cryptography;
using System.Collections.Specialized;
class WebhookResponse {
string Currency,
string Amount,
string LinkRef,
string MerchantOrderRef,
string CountryCode,
string Status,
string Signature,
}
namespace Signature {
public class Signature {
private bool VerifySignature(WebhookResponse webhookResponse, string secret) {
NameValueCollection myCollection = System.Web.HttpUtility.ParseQueryString(string.Empty);
myCollection.Add("currency", webhookResponse.Currency);
myCollection.Add("amount", webhookResponse.Amount);
myCollection.Add("link_ref", webhookResponse.LinkRef);
myCollection.Add("merchant_order_ref", webhookResponse.MerchantOrderRef);
myCollection.Add("country_code", webhookResponse.CountryCode);
myCollection.Add("status", webhookResponse.Status);
string message = myCollection.ToString();
var encoding = new System.Text.ASCIIEncoding();
byte[] keyByte = encoding.GetBytes(secret);
byte[] messageBytes = encoding.GetBytes(message);
var hmacsha256 = new HMACSHA256(keyByte);
byte[] hashmessage = hmacsha256.ComputeHash(messageBytes);
string hash_value = Convert.ToBase64String(hashmessage);
if (hash_value !== webhookResponse.Signature) {
Console.WriteLine("Hash verification failed, not from valid source")
return false;
} else {
Console.WriteLine("Hash verification succeded")
return true;
}
}
}
}
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
import java.util.Map;
public class Main {
public static void main(String[] args) {
WebhookSigValResponseObj webhookResponseObj = new WebhookSigValResponseObj(
"THB", "100", "linkRefValue", "merchantOrderRefValue",
"US", "success", "signatureValue"
);
boolean isValid = verifySignature(webhookResponseObj, "yourSecretKey");
System.out.println("Is signature valid? " + isValid);
}
public static boolean verifySignature(WebhookSigValResponseObj webhookResponseObj, String secretKey) {
try {
StringBuilder data = new StringBuilder();
data.append("amount=").append(webhookResponseObj.getAmount())
.append("&country_code=").append(webhookResponseObj.getCountryCode())
.append("¤cy=").append(webhookResponseObj.getCurrency())
.append("&link_ref=").append(webhookResponseObj.getLinkRef())
.append("&merchant_order_ref=").append(webhookResponseObj.getMerchantOrderRef())
.append("&status=").append(webhookResponseObj.getStatus());
byte[] secret = secretKey.getBytes();
byte[] message = data.toString().getBytes();
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(secret, "HmacSHA256");
sha256_HMAC.init(secretKeySpec);
byte[] hash = sha256_HMAC.doFinal(message);
String computedSignature = Base64.getEncoder().encodeToString(hash);
// Compare computed signature to the one received in webhook response
if (!computedSignature.equals(webhookResponseObj.getSignature())) {
System.out.println("Hash verification failed, not from a valid source");
return false;
} else {
System.out.println("Hash verification succeeded");
return true;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
class WebhookSigValResponseObj {
private String currency;
private String amount;
private String linkRef;
private String merchantOrderRef;
private String countryCode;
private String status;
private String signature;
public WebhookSigValResponseObj(String currency, String amount, String linkRef, String merchantOrderRef, String countryCode, String status, String signature) {
this.currency = currency;
this.amount = amount;
this.linkRef = linkRef;
this.merchantOrderRef = merchantOrderRef;
this.countryCode = countryCode;
this.status = status;
this.signature = signature;
}
public String getCurrency() {
return currency;
}
public String getAmount() {
return amount;
}
public String getLinkRef() {
return linkRef;
}
public String getMerchantOrderRef() {
return merchantOrderRef;
}
public String getCountryCode() {
return countryCode;
}
public String getStatus() {
return status;
}
public String getSignature() {
return signature;
}
}
#!/usr/bin/python
# -*- coding: utf-8 -*-
import urllib
import hashlib
import hmac
import base64
class WebhookResponseObj:
def __init__(self, Currency, Amount, LinkRef, MerchantOrderRef, CountryCode, Status, Signature):
# Instance Variable
self.Currency = Currency
self.Amount = Amount
self.LinkRef = LinkRef
self.MerchantOrderRef = MerchantOrderRef
self.CountryCode = CountryCode
self.Status = Status
self.Signature = Signature
def GenerateSignature(WebhookResponseObj, secretKey):
f = {
'currency': WebhookResponseObj.Currency,
'amount': WebhookResponseObj.Amount,
'link_ref': WebhookResponseObj.LinkRef,
'merchant_order_ref': WebhookResponseObj.MerchantOrderRef,
'country_code': WebhookResponseObj.CountryCode,
'status': WebhookResponseObj.Status,
}
message1 = urllib.urlencode(f)
message = bytes(message1).encode('utf-8')
secret = bytes(secretKey).encode('utf-8')
signature = base64.b64encode(hmac.new(secret, message, digestmod=hashlib.sha256).digest())
if (signature !== WebhookResponseObj.Signature) {
Print("Hash verification failed, not from valid source")
return false;
} else {
Print("Hash verification succeded")
return true;
}