Regular Plan

Introduction

PortOne API payment requests are signed to ensure their authenticity and integrity. This document provides guidelines on how to generate signature for a regular plan request.

Steps

To generate a signature for a regular plan request, follow these steps:

  1. Concatenate the required parameters of the request into a single string in alphabetical order.
  2. Calculate the SHA-256 hash of the resulting string.
  3. 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
	Frequency        int64
	MerchantOrderRef 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("frequency", strconv.Itoa(int(requestObj.Frequency)))
	params.Add("merchant_order_ref", requestObj.MerchantOrderRef)

	// 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 := ""

	requestObj := RequestObj{
		Amount:           100.00,
		ClientKey:        portOneKey,
		Currency:         "USD",
		Frequency:        12,
		MerchantOrderRef: merchantOrderRef,
	}

	// 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,
      'frequency' => $requestObj->Frequency,
      'merchant_order_ref' => $requestObj->MerchantOrderRef
  );
  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 = "";
    // Example request object
    $requestObj = (object) [
        'Amount' => 100.00,
        'ClientKey' => $key,
        'Currency' => 'USD',
        'Frequency' => 12,
        'MerchantOrderRef' => $merchant_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('frequency', requestObj.Frequency);
    params.append('merchant_order_ref', requestObj.MerchantOrderRef);
    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 = '';

const requestObj = {
    Amount: 100.00,
    ClientKey: clientKey,
    Currency: 'USD',
    Frequency: 12,
    MerchantOrderRef: merchantOrderRef
};

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 int Frequency;
        public string MerchantOrderRef;
    }

    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 },
                { "frequency", paymentRequest.Frequency.ToString() },
                { "merchant_order_ref", paymentRequest.MerchantOrderRef }
            };

            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 = "";
            PaymentRequest paymentRequest = new PaymentRequest()
            {
                Amount = 100.00,
                ClientKey = key,
                Currency = "USD",
                Frequency = 12,
                MerchantOrderRef = merchantOrderRef
            };
            

            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 = "";
        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.setFrequency(12);
        requestObj.setMerchantOrderRef(merchantOrderRef);

        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("frequency", requestObj.getFrequency().toString());
            params.put("merchant_order_ref", requestObj.getMerchantOrderRef());

            // 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 Integer frequency;
    private String merchantOrderRef;

    // 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 setFrequency(Integer frequency) {
        this.frequency = frequency;
    }

    // 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 Integer getFrequency() {
        return frequency;
    }
}
#!/usr/bin/python
# -*- coding: utf-8 -*-
import urllib.parse
import hashlib
import hmac
import base64

class RequestObj:   
    def __init__(self, Amount, ClientKey, Currency, Frequency, MerchantOrderRef):
        # Instance Variables    
        self.Amount = Amount
        self.ClientKey = ClientKey
        self.Currency = Currency    
        self.Frequency = Frequency 
        self.MerchantOrderRef = MerchantOrderRef

def GenerateSignature(requestObj, secretKey):
    f = {
        'amount': f"{requestObj.Amount:.2f}".rstrip('0').rstrip('.'),
        'client_key': requestObj.ClientKey,
        'currency': requestObj.Currency,
        'frequency': requestObj.Frequency,
        'merchant_order_ref': requestObj.MerchantOrderRef
    }
    
    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 = ''
# Create an instance of RequestObj
requestObj = RequestObj(
    Amount=100.00,
    ClientKey=key,
    Currency='USD',
    Frequency=12,
    MerchantOrderRef=merchantOrderRef
)

# Call GenerateSignature
signature = GenerateSignature(requestObj, secret)
print(f'Signature: {signature}\n')

Parameter list to generate signature

amount
float64

The amount of the plan


client_key
string

The PortOne key of the merchant


currency
string

The currency of the plan


frequency
string

The frequency of the plan


merchant_order_ref
string

Order Reference sent by merchant to create the plan


📘

Note

Refer to Plan Request for the complete list of plan request parameters.