Ondemand Deduction
Introduction
PortOne API payment requests are signed to ensure their authenticity and integrity. This document provides guidelines on how to generate signature for an ondemand deduction request.
Steps
To generate a signature for an ondemand deduction request, follow these steps:
- Concatenate the required parameters of the request into a single string in alphabetical order.
- Calculate the SHA-256 hash of the resulting string.
- Base64-encode the hash to obtain the signature.
Code Examples
package main
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"fmt"
"net/url"
"strconv"
)
type RequestObj struct {
Amount float64
ClientKey string
Currency string
MerchantOrderRef string
SubscriptionOrderRef string
}
func GenerateSignature(requestObj RequestObj, portOneSecret string) string {
// Create a url.Values map and add the necessary parameters
params := make(url.Values)
params.Add("amount", strconv.FormatFloat(requestObj.Amount, 'f', -1, 64))
params.Add("client_key", requestObj.ClientKey)
params.Add("currency", requestObj.Currency)
params.Add("merchant_order_ref", requestObj.MerchantOrderRef)
params.Add("subscription_order_ref", requestObj.SubscriptionOrderRef)
// Encode the parameters
data := params.Encode()
// fmt.Println("data is:", data)
// Create the HMAC hash using SHA-256
secret := []byte(portOneSecret)
message := []byte(data)
hash := hmac.New(sha256.New, secret)
hash.Write(message)
// Convert the hash to a base64 string
hashValue := base64.StdEncoding.EncodeToString(hash.Sum(nil))
return hashValue
}
func main() {
portOneKey := "PORTONE_KEY"
portOneSecret := "PORTONE_SECRET"
// The unique merchant order reference generated by the merchant
merchantOrderRef := ""
// The subscription link's order reference to which you want to make an ondemand deduction
subscriptionOrderRef := ""
requestObj := RequestObj{
Amount: 100.00,
ClientKey: portOneKey,
Currency: "USD",
MerchantOrderRef: merchantOrderRef,
SubscriptionOrderRef: subscriptionOrderRef,
}
// Generate the signature
signature := GenerateSignature(requestObj, portOneSecret)
// Output the signature
fmt.Println("Signature is:", signature)
}
<?php
function GenerateSignature($requestObj, $secretKey) {
$data = array(
'amount' => $requestObj->Amount,
'client_key' => $requestObj->ClientKey,
'currency' => $requestObj->Currency,
'merchant_order_ref' => $requestObj->MerchantOrderRef,
'subscription_order_ref' => $requestObj->SubscriptionOrderRef
);
ksort($data);
$data = http_build_query($data);
$message = $data;
return base64_encode(hash_hmac('sha256', $message, $secretKey, true));
}
function main() {
$key = "PORTONE_KEY";
$secret_key = "PORTONE_SECRET";
// The unique merchant order reference generated by the merchant
$merchant_order_ref = "";
// The subscription link's order reference to which you want to make an ondemand deduction
$subscription_order_ref = "";
// Example request object
$requestObj = (object) [
'Amount' => 100.00,
'ClientKey' => $key,
'Currency' => 'USD',
'MerchantOrderRef' => $merchant_order_ref,
'SubscriptionOrderRef' => $subscription_order_ref
];
$signature = GenerateSignature($requestObj, $secret_key);
echo "Signature: " . $signature;
}
main();
?>
const crypto = require('crypto');
const { URLSearchParams } = require('url');
function GenerateSignature(requestObj, secretKey) {
const params = new URLSearchParams();
params.append('amount', requestObj.Amount);
params.append('client_key', requestObj.ClientKey);
params.append('currency', requestObj.Currency);
params.append('merchant_order_ref', requestObj.MerchantOrderRef);
params.append('subscription_order_ref', requestObj.SubscriptionOrderRef);
params.sort();
const message = params.toString();
const hashValue = crypto.createHmac('sha256', secretKey).update(message).digest('base64');
return hashValue;
}
const clientKey = 'PORTONE_KEY';
const secretKey = 'PORTONE_SECRET';
// The unique merchant order reference generated by the merchant
const merchantOrderRef = '';
// The subscription link's order reference to which you want to make an ondemand deduction
const subscriptionOrderRef = '';
const requestObj = {
Amount: 100.00,
ClientKey: clientKey,
Currency: 'USD',
MerchantOrderRef: merchantOrderRef,
SubscriptionOrderRef: subscriptionOrderRef
};
const signature = GenerateSignature(requestObj, secretKey);
console.log(`Signature: ${signature}\n`);
using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
namespace ConsoleApp
{
class PaymentRequest
{
public double Amount;
public string ClientKey;
public string Currency;
public string MerchantOrderRef;
public string SubscriptionOrderRef;
}
class ApiSecurityExample
{
public static string GenerateSignature(PaymentRequest paymentRequest, string secret)
{
var map = new SortedDictionary<string, string>()
{
{ "amount", RemoveTrailingZeros(paymentRequest.Amount) },
{ "client_key", paymentRequest.ClientKey },
{ "currency", paymentRequest.Currency },
{ "merchant_order_ref", paymentRequest.MerchantOrderRef },
{ "subscription_order_ref", paymentRequest.SubscriptionOrderRef }
};
var stringBuilder = new StringBuilder();
foreach (var key in map.Keys)
{
if (stringBuilder.Length > 0)
{
stringBuilder.Append("&");
}
var value = map[key];
try
{
stringBuilder.Append((key != null ? Uri.EscapeDataString(key) : ""));
stringBuilder.Append("=");
stringBuilder.Append(value != null ? Uri.EscapeDataString(value) : "");
}
catch (ArgumentNullException e)
{
throw new Exception("The key or value is null.", e);
}
catch (UriFormatException e)
{
throw new Exception("Invalid format for key or value.", e);
}
}
var message = stringBuilder.ToString();
// Console.WriteLine("message: " + message);
var encoding = new 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);
return hash_value;
}
private static string RemoveTrailingZeros(double amount)
{
return amount.ToString("0.###################");
}
}
class Program
{
static void Main(string[] args)
{
string key = "PORTONE_KEY";
string secret = "PORTONE_SECRET";
// The unique merchant order reference generated by the merchant
string merchantOrderRef = "";
// The subscription link's order reference to which you want to make an ondemand deduction
string subscriptionOrderRef = "";
PaymentRequest paymentRequest = new PaymentRequest()
{
Amount = 100.00,
ClientKey = key,
Currency = "USD",
MerchantOrderRef = merchantOrderRef,
SubscriptionOrderRef = subscriptionOrderRef
};
string signature = ApiSecurityExample.GenerateSignature(paymentRequest, secret);
Console.WriteLine("Signature: " + signature);
}
}
}
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.text.DecimalFormat;
import java.util.Map;
import java.util.TreeMap;
public class Main {
public static void main(String[] args) {
String key = "PORTONE_KEY";
String secret = "PORTONE_SECRET";
// The unique merchant order reference generated by the merchant
String merchantOrderRef = "";
// The subscription link's order reference to which you want to make an ondemand deduction
String subscriptionOrderRef = "";
String currency = "USD";
Double amount = 100.00;
// Create an instance of RequestObj using the default constructor
RequestObj requestObj = new RequestObj();
// Use setter methods to set the values
requestObj.setAmount(amount);
requestObj.setClientKey(key);
requestObj.setCurrency(currency);
requestObj.setMerchantOrderRef(merchantOrderRef);
requestObj.setSubscriptionOrderRef(subscriptionOrderRef);
String signature = generateSignature(requestObj, secret);
System.out.println("Signature: " + signature);
}
public static String generateSignature(RequestObj requestObj, String secretKey) {
try {
Map<String, String> params = new TreeMap<>();
params.put("amount", requestObj.getAmount());
params.put("client_key", requestObj.getClientKey());
params.put("currency", requestObj.getCurrency());
params.put("merchant_order_ref", requestObj.getMerchantOrderRef());
params.put("subscription_order_ref", requestObj.getSubscriptionOrderRef());
// Encode the parameters
String data = encodeParams(params);
// System.out.println("data: " + data);
Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getBytes(), "HmacSHA256");
sha256_HMAC.init(secretKeySpec);
byte[] hash = sha256_HMAC.doFinal(data.getBytes());
return Base64.getEncoder().encodeToString(hash);
} catch (Exception e) {
throw new RuntimeException("Failed to calculate hmac-sha256", e);
}
}
public static String encodeParams(Map<String, String> params) {
StringBuilder encodedParams = new StringBuilder();
for (Map.Entry<String, String> entry : params.entrySet()) {
if (encodedParams.length() > 0) {
encodedParams.append("&");
}
encodedParams.append(URLEncoder.encode(entry.getKey(), StandardCharsets.UTF_8))
.append("=")
.append(URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8));
}
return encodedParams.toString();
}
}
class RequestObj {
private Double amount;
private String clientKey;
private String currency;
private String merchantOrderRef;
private String subscriptionOrderRef;
// Default constructor
public RequestObj() {
}
// Setter methods
public void setClientKey(String clientKey) {
this.clientKey = clientKey;
}
public void setCurrency(String currency) {
this.currency = currency;
}
public void setAmount(Double amount) {
this.amount = amount;
}
public void setMerchantOrderRef(String merchantOrderRef) {
this.merchantOrderRef = merchantOrderRef;
}
public void setSubscriptionOrderRef(String subscriptionOrderRef) {
this.subscriptionOrderRef = subscriptionOrderRef;
}
// Getter methods
public String getClientKey() {
return clientKey;
}
public String getCurrency() {
return currency;
}
public String getAmount() {
DecimalFormat df = new DecimalFormat("0.##");
return df.format(amount);
}
public String getMerchantOrderRef() {
return merchantOrderRef;
}
public String getSubscriptionOrderRef() {
return subscriptionOrderRef;
}
}
#!/usr/bin/python
# -*- coding: utf-8 -*-
import urllib.parse
import hashlib
import hmac
import base64
class RequestObj:
def __init__(self, Amount, ClientKey, Currency, MerchantOrderRef, SubscriptionOrderRef):
# Instance Variables
self.Amount = Amount
self.ClientKey = ClientKey
self.Currency = Currency
self.MerchantOrderRef = MerchantOrderRef
self.SubscriptionOrderRef = SubscriptionOrderRef
def GenerateSignature(requestObj, secretKey):
f = {
'amount': f"{requestObj.Amount:.2f}".rstrip('0').rstrip('.'),
'client_key': requestObj.ClientKey,
'currency': requestObj.Currency,
'merchant_order_ref': requestObj.MerchantOrderRef,
'subscription_order_ref': requestObj.SubscriptionOrderRef
}
f = dict(sorted(f.items()))
message1 = urllib.parse.urlencode(f)
message = message1.encode('utf-8')
# print(f'message: {message}\n')
secret = secretKey.encode('utf-8')
signature = base64.b64encode(hmac.new(secret, message, digestmod=hashlib.sha256).digest()).decode('utf-8')
return signature
# Define constants
key = 'PORTONE_KEY'
secret = 'PORTONE_SECRET'
# The unique merchant order reference generated by the merchant
merchantOrderRef = ''
# The subscription link's order reference to which you want to make an ondemand deduction
subscriptionOrderRef = ''
# Create an instance of RequestObj
requestObj = RequestObj(
Amount=100.00,
ClientKey=key,
Currency='USD',
MerchantOrderRef=merchantOrderRef,
SubscriptionOrderRef=subscriptionOrderRef
)
# Call GenerateSignature
signature = GenerateSignature(requestObj, secret)
print(f'Signature: {signature}\n')
Parameter list to generate signature
amount
amount
float64
The amount of the deduction
client_key
client_key
string
The PortOne key of the merchant
currency
currency
string
The currency of the ondemand transaction
merchant_order_ref
merchant_order_ref
string
Order Reference sent by merchant to create the ondemand transaction
subscription_order_ref
subscription_order_ref
string
The subscription order reference of the subscription link
Note
Refer to Ondemand Deduction Request for the complete list of ondemand deduction request parameters.
Updated 7 days ago