---
updatedAt: 2025-09-18T11:22:43.000Z
agentTools:
  projectIndex: https://docs.portone.cloud/llms.txt
---

# Subscription: Creating an OnDemand Deduction

```node Node
const crypto = require('crypto');

// 1. Set the PortOne Key, PortOne Secret and JWT token 
const PORTONE_KEY = '{PORTONE_KEY}'; // Enter your PortOne Key here
const PORTONE_SECRET = '{PORTONE_SECRET}'; // Enter your PortOne Secret here
const JWT = '{JWT}'; // Refer to https://docs.portone.cloud/docs/jwt-authentication for generating JWT token

// 2. Function to generate the signature using request data and PortOne Secret Key
function generateSignature(requestObj, secretKey) {
    const params = new URLSearchParams();

    // Append required parameters for signature generation
    params.append('amount', requestObj.amount);
    params.append('client_key', requestObj.portone_key);
    params.append('currency', requestObj.currency);
    params.append('merchant_order_ref', requestObj.merchant_order_ref);
    params.append('subscription_order_ref', requestObj.subscription_order_ref);

    // Sort the parameters by key
    const sortedParams = [...params.entries()].sort();
    const sortedSearchParams = new URLSearchParams(sortedParams);

    // Convert parameters to string and generate HMAC-SHA256 hash
    const message = sortedSearchParams.toString();
    const hashValue = crypto.createHmac('sha256', secretKey).update(message).digest('base64');

    return hashValue;
}

// 3. Function to create headers
const createHeaders = (portoneKey, jwtToken) => {
  return {
    accept: 'application/json',
    'Content-Type': 'application/json',
    'X-Portone-Client-Key': portoneKey,
    Authorization: `Bearer ${jwtToken}`
  };
};

// 4. Define the complete payload data adhering to the provided JSON schema
// Refer https://docs.portone.cloud/reference/post_api-subscription-creatededuction for detailed information on the various payload fields
const payloadData = {
  portone_key: PORTONE_KEY,
  merchant_order_ref: 'Merchant_1729672233763', // Enter the merchant order reference for the deduction transaction
  subscription_order_ref: '2nsRMeHXpSUpe8DZzdyZkKCtI9D', // Enter the subscription order reference with which you want to deduct the amount
  description: "Product name for the customer's subscription purchase", // Product name for the customer's subscription purchase
  source: 'api',
  amount: 100,
  currency: 'USD',
  environment: 'sandbox',
};

// 5. Generate the signature using the payload
const signatureHash = generateSignature(payloadData, PORTONE_SECRET);

// 6. Add the signature to the payload
payloadData.signature_hash = signatureHash;

// 7. Creating the options for the fetch call
const options = {
  method: 'POST',
  headers: createHeaders(PORTONE_KEY, JWT),
  body: JSON.stringify(payloadData)
};

// 8. Execute the fetch call
fetch('https://api.portone.cloud/api/subscription/createDeduction', options)
  .then(res => res.json())
  .then(handleSuccess) // Call handleSuccess for successful responses
  .catch(handleError); // Call handleError for errors

// Function to handle successful response
function handleSuccess(res) {
    console.log("Response:", res); // handle success response
}

// Function to handle error
function handleError(err) {
    console.error("Error:", err); // handle error response
}
```

```json Response Example
{"success":true}
```

# Setup

<!-- node@3-6 -->

Setup the PortOne Key, Secret and JWT Token

# Creating Payload

<!-- node@40-51 -->



# Generating signature hash from payload

<!-- node@53-57,8-28 -->



# Calling PortOne Create Subscription Deduction API

<!-- node@59-70 -->

Refer https://docs.portone.cloud/reference/post_api-subscription-creatededuction for detailed information on the Create Subscription Deduction API

# Handling The Response

<!-- node@72-80 -->