Skip to main content

Place order with existing payment methods

Overview

2Checkout supports 1-click purchases for returning customers who paid for their previous orders with:

  • Credit/Debit cards

How does this work?

  1. Identify returning customers.
  2. Retrieve the payment method token.
  3. Collect the CVV from the customer.
  4. Place a new order using a valid payment method token and CVV.
  5. 2Checkout charges returning customers using their payment-on-file information.

Requirements

  • TransientToken required for the placeOrder method. Can be retrieved from getCustomerInformation.
  • This method only woks with Credit/Debit cards.

Parameters

Parameters Type/Description
sessionID Required (string)
  Session identifier, the output of the Login method. Include sessionID into all your requests. 2Checkout throws an exception if the values are incorrect. The sessionID expires in 10 minutes.
Order Required (Object)
  Object designed to collect all data necessary for an order, including billing, product/subscription plan and payment details.

Response

Parameters Type/Description
Order information Object
  Object containing order information.

Retrieve customer existent payment methods

<?php

declare(strict_types=1);

class Configuration
{
    public const MERCHANT_CODE = 'MERCHANT_CODE';
    public const MERCHANT_KEY = 'SECRET_KEY';
    public const URL = 'https://api.2checkout.com/rpc/6.0';
    public const ACTION = 'getCustomerInformation';
    public const CUSTOMER_REF = '1111';
    public const INCLUDE_PAYMENT_DATA = true;
    //array or JSON
    public const PAYLOAD = null;
}

class Client
{
    private const LOGIN_METHOD = 'login';
    private $calls = 1;
    private $sessionId;
    private function generateAuth(): array
    {
        $merchantCode = Configuration::MERCHANT_CODE;
        $key = Configuration::MERCHANT_KEY;
        $date = gmdate('Y-m-d H:i:s');
        $string = strlen($merchantCode) . $merchantCode . strlen($date) . $date;
        $hash = hash_hmac('md5', $string, $key);
        return compact('merchantCode', 'date', 'hash');
    }
    public function login(string $url)
    {
        $payload = $this->generateAuth();
        $response = $this->call($url, array_values($payload), self::LOGIN_METHOD);
        $this->sessionId = $response['result'];
    }
    public function call(
        string $url = Configuration::URL,
        $payload = Configuration::PAYLOAD,
        string $action = Configuration::ACTION
    ): ?array {
        if (empty($this->sessionId) && $action !== self::LOGIN_METHOD) {
            $this->login($url);
        }

        if(is_string($payload)) {
            $payload = json_decode($payload, true);
        }
        if (!empty($this->sessionId)) {
            $payload = [$this->sessionId, Configuration::CUSTOMER_REF, Configuration::CUSTOMER_REF, Configuration::INCLUDE_PAYMENT_DATA, $payload];
        }
        $payload = array_filter($payload);

        $request = json_encode([
            'jsonrpc' => '2.0',
            'method' => $action,
            'params' => $payload,
            'id' => $this->calls++,
        ]);

        $curl = curl_init($url);
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($curl, CURLOPT_SSLVERSION, 0);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json', 'Accept: application/json', 'Cookie: XDEBUG_SESSION=PHPSTORM'));
        curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
        $response = curl_exec($curl);
        if(empty($response)) {
            die('Server unavailable');
        }
        echo $response . '</br>';
        return json_decode($response, true);;
    }
}
$client = new Client();
$result = $client->call();
var_dump($result);

Response

Parameters Type/Description
Customer Object

 

Place an order using existing payment data

<?php
require('PATH_TO_AUTH');
$oldOrderExistent = callRPC((Object)$jsonRpcRequest, $host, true);
$Order = new stdClass();
$Order->RefNo = NULL;
$Order->Currency = 'usd';
$Order->Country = 'US';
$Order->Language = 'en';
$Order->CustomerIP = '91.220.121.21';
$Order->ExternalReference = NULL;
$Order->Source = NULL;
$Order->Affiliate = new stdClass();
$Order->Affiliate->AffiliateCode = 'Partner123'
$Order->Affiliate->AffiliateSource = 'MobilePlatform'
$Order->CustomerReference = NULL;
$Order->Items = array();
$Order->Items[0] = new stdClass();
$Order->Items[0]->Code = 'my_subscription_1';
$Order->Items[0]->Quantity = 1;
$Order->Items[0]->PriceOptions = NULL;
$Order->Items[0]->SKU = NULL;
$Order->Items[0]->Price = NULL;
$Order->Items[0]->CrossSell = NULL;
$Order->Items[0]->Trial = false;
$Order->BillingDetails = new stdClass();
$Order->BillingDetails->Email = $oldOrderExistent->BillingDetails->Email;;
$Order->DeliveryDetails = NULL;
$Order->PaymentDetails = new stdClass ();
$Order->PaymentDetails->Type = 'EXISTING_PAYMENT_DATA';
$Order->PaymentDetails->Currency = 'usd';
$Order->PaymentDetails->PaymentMethod = new stdClass ();
$Order->PaymentDetails->CustomerIP = '10.10.10.10';
$Order->PaymentDetails->PaymentMethod->TransientToken= 'oj5iyozmtkvuirzybvmwyhl3bl3nuxa44rkg5r1h';
$Order->PaymentDetails->PaymentMethod->CCID = '123';
$Order->PaymentDetails->PaymentMethod->Vendor3DSReturnURL = "http://www.success.ro";
$Order->PaymentDetails->PaymentMethod->Vendor3DSCancelURL = "http://www.error.ro"; 
$Order->Promotions = NULL;
$Order->AdditionalFields = NULL;
$Order->LocalTime = NULL;
$Order->GiftDetails = NULL;
$jsonRpcRequest = array (
'method' => 'placeOrder',
'params' => array($sessionID, $Order),
'id' => $i++,
'jsonrpc' => '2.0'
);
var_dump (callRPC((Object)$jsonRpcRequest, $host, true)); 

Remove scheduled subscription changes

Overview

Delete subscription changes scheduled to be applied at the end of the billing cycle. Use the removeScheduledProductUpdate method to remove the changes.

Parameters

Parameters Type/Description
sessionID Required (string)
  Session identifier, the output of the Login method. Include sessionID into all your requests. 2Checkout throws an exception if the values are incorrect.  The sessionID expires in 10 minutes.
SubscriptionReference Required (String)
  The system-generated reference code of the subscription.

Response

Parameters Type/Description
Boolean true or false depending on whether the changes were successful or not.

Request

<?php

require('PATH_TO_AUTH');

$subscriptionReference = 'YOUR_SUBSCRIPTION_REFERENCE';

$jsonRpcRequest = [
    'method' => 'removeScheduledProductUpdate',
    'params' => [$sessionID, $subscriptionReference],
    'id' => $i++,
    'jsonrpc' => '2.0'
];

var_dump(callRPC((object)$jsonRpcRequest, $host, true));

FAQ:

When is the scheduled update applied? At the next renewal - for both auto-renewals and manual renewals.

Is there a limit on how far in advance I can schedule an update? No specific time limit is enforced - the update remains scheduled until the next renewal or until explicitly removed.

How late in the billing cycle can an update be scheduled? At any point during the billing cycle, right up until the renewal.

Can I schedule changes to product, pricing options, and quantity at the same time? Yes. ProductCode, PricingOptions, and Quantity can be combined in a single scheduling call.

Can I schedule a quantity decrease? Yes. A quantity decrease is supported, but Quantity = 0 and negative values are not allowed and will return validation errors.

Are all pricing option types supported for scheduled subscription changes? Yes, with one exception: pay-per-usage (PAYPERUSAGE) pricing options are not supported.

Where can I see the scheduled update? In the GET subscription response under Future Events, and in the license history in the Control Panel and MyAccount after the update is applied.

Are shoppers notified when a subscription change is scheduled? No. Scheduling a subscription change does not trigger a notification to the shopper, however, an LCN will be sent to the vendor who can then decide to notify the shopper.

Does the renewal price reflect the scheduled changes? Yes. The GET renewal price APIs return pricing based on the scheduled changes.

Is the scheduled update applied if the subscription is renewed manually via MyAccount? Yes. The scheduled update is respected across all renewal paths.

Does an existing coupon still apply after a scheduled product change? Yes, provided the coupon is compatible with the new product. If the coupon is not compatible with the product being updated to, it will not be applied after the change.

Does an early renewal honor the scheduled changes? Yes. Early renewals respect the scheduled update - the subscription will renew with the new product, pricing options, and/or quantity as defined in the scheduled change.

Is bulk scheduling across multiple subscriptions supported? No. Scheduling is performed per individual subscription reference. Bulk scheduling across multiple subscriptions in a single API call is not supported — the API is designed specifically for one subscription at a time.

 

Schedule subscription changes

Overview

Schedule specific changes for a subscription to be applied at the end of the billing cycle. Use the scheduledProductUpdate method to change specific details about a subscription.

Parameters

Parameters Type/Description
sessionID Required (string)
  Session identifier, the output of the Login method. Include sessionID into all your requests. 2Checkout throws an exception if the values are incorrect.  The sessionID expires in 10 minutes.
SubscriptionReference Required (String)
  The system-generated reference code of the subscription.
ProductCode String 
  Unique product identifier that you control to which the subscription should be updated.
PricingOptions Array
  The product options codes selected for the subscription update. Pricing options codes are case sensitive.
Quantity Int
  Number of product units

Response

Parameters Type/Description
Boolean true or false depending on whether the changes were successful or not.

Request

<?php

require('PATH_TO_AUTH');

$subscriptionReference = 'YOUR_SUBSCRIPTION_REFERENCE';
$newProductCode        = 'PRODUCT_V2';
$newPricingOptions     = 'OPTION_CODE1;OPTION_CODE2';
$newQuantity           = 2;

$jsonRpcRequest = [
    'method' => 'scheduleProductUpdate',
    'params' => [$sessionID, $subscriptionReference, $newProductCode, $newPricingOptions, $newQuantity],
    'id' => $i++,
    'jsonrpc' => '2.0'
];

var_dump(callRPC((object)$jsonRpcRequest, $host, true));

FAQ:

When is the scheduled update applied? At the next renewal - for both auto-renewals and manual renewals.

Is there a limit on how far in advance I can schedule an update? No specific time limit is enforced - the update remains scheduled until the next renewal or until explicitly removed.

How late in the billing cycle can an update be scheduled? At any point during the billing cycle, right up until the renewal.

Can I schedule changes to product, pricing options, and quantity at the same time? Yes. ProductCode, PricingOptions, and Quantity can be combined in a single scheduling call.

Can I schedule a quantity decrease? Yes. A quantity decrease is supported, but Quantity = 0 and negative values are not allowed and will return validation errors.

Are all pricing option types supported for scheduled subscription changes? Yes, with one exception: pay-per-usage (PAYPERUSAGE) pricing options are not supported.

Where can I see the scheduled update? In the GET subscription response under Future Events, and in the license history in the Control Panel and MyAccount after the update is applied.

Are shoppers notified when a subscription change is scheduled? No. Scheduling a subscription change does not trigger a notification to the shopper, however, an LCN will be sent to the vendor who can then decide to notify the shopper.

Does the renewal price reflect the scheduled changes? Yes. The GET renewal price APIs return pricing based on the scheduled changes.

Is the scheduled update applied if the subscription is renewed manually via MyAccount? Yes. The scheduled update is respected across all renewal paths.

Does an existing coupon still apply after a scheduled product change? Yes, provided the coupon is compatible with the new product. If the coupon is not compatible with the product being updated to, it will not be applied after the change.

Does an early renewal honor the scheduled changes? Yes. Early renewals respect the scheduled update - the subscription will renew with the new product, pricing options, and/or quantity as defined in the scheduled change.

 Is bulk scheduling across multiple subscriptions supported? No. Scheduling is performed per individual subscription reference. Bulk scheduling across multiple subscriptions in a single API call is not supported — the API is designed specifically for one subscription at a time.

 

Remove scheduled subscription changes

Overview

Delete subscription changes scheduled to be applied at the end of the billing cycle. Use the removeScheduledProductUpdate method to remove the changes.

Parameters

Parameters Type/Description
sessionID Required (string)
  Session identifier, the output of the Login method. Include sessionID into all your requests. 2Checkout throws an exception if the values are incorrect.  The sessionID expires in 10 minutes.
SubscriptionReference Required (String)
  The system-generated reference code of the subscription.

Response

Parameters Type/Description
Boolean true or false depending on whether the changes were successful or not.

Request

<?php

require ('PATH_TO_AUTH');

$subscriptionReference = 'YOUR_SUBSCRIPTION_REFERENCE';

try {
    $scheduledProductUpdate = $client->removeScheduledProductUpdate($sessionID, $subscriptionReference);
} catch (SoapFault $e) {
    echo "removeScheduledProductUpdate: " . $e->getMessage();
    exit;
}

var_dump("removeScheduledProductUpdate", $scheduledProductUpdate);

FAQ:

When is the scheduled update applied? At the next renewal - for both auto-renewals and manual renewals.

Is there a limit on how far in advance I can schedule an update? No specific time limit is enforced - the update remains scheduled until the next renewal or until explicitly removed.

How late in the billing cycle can an update be scheduled? At any point during the billing cycle, right up until the renewal.

Can I schedule changes to product, pricing options, and quantity at the same time? Yes. ProductCode, PricingOptions, and Quantity can be combined in a single scheduling call.

Can I schedule a quantity decrease? Yes. A quantity decrease is supported, but Quantity = 0 and negative values are not allowed and will return validation errors.

Are all pricing option types supported for scheduled subscription changes? Yes, with one exception: pay-per-usage (PAYPERUSAGE) pricing options are not supported.

Where can I see the scheduled update? In the GET subscription response under Future Events, and in the license history in the Control Panel and MyAccount after the update is applied.

Are shoppers notified when a subscription change is scheduled? No. Scheduling a subscription change does not trigger a notification to the shopper, however, an LCN will be sent to the vendor who can then decide to notify the shopper.

Does the renewal price reflect the scheduled changes? Yes. The GET renewal price APIs return pricing based on the scheduled changes.

Is the scheduled update applied if the subscription is renewed manually via MyAccount? Yes. The scheduled update is respected across all renewal paths.

Does an existing coupon still apply after a scheduled product change? Yes, provided the coupon is compatible with the new product. If the coupon is not compatible with the product being updated to, it will not be applied after the change.

Does an early renewal honor the scheduled changes? Yes. Early renewals respect the scheduled update - the subscription will renew with the new product, pricing options, and/or quantity as defined in the scheduled change.

 Is bulk scheduling across multiple subscriptions supported? No. Scheduling is performed per individual subscription reference. Bulk scheduling across multiple subscriptions in a single API call is not supported — the API is designed specifically for one subscription at a time.

 

Schedule subscription changes

Overview

Schedule specific changes for a subscription to be applied at the end of the billing cycle. Use the scheduledProductUpdate method to change specific details about a subscription.

Parameters

Parameters Type/Description
sessionID Required (string)
  Session identifier, the output of the Login method. Include sessionID into all your requests. 2Checkout throws an exception if the values are incorrect.  The sessionID expires in 10 minutes.
SubscriptionReference Required (String)
  The system-generated reference code of the subscription.
ProductCode String 
  Unique product identifier that you control to which the subscription should be updated.
PricingOptions Array
  The product options codes selected for the subscription update. Pricing options codes are case sensitive.
Quantity Int
  Number of product units

Response

Parameters Type/Description
Boolean true or false depending on whether the changes were successful or not.

Request

<?php

require ('PATH_TO_AUTH');

$subscriptionReference = 'YOUR_SUBSCRIPTION_REFERENCE';
$newProductCode        = 'PRODUCT_V2';
$newPricingOptions     = 'OPTION_CODE1;OPTION_CODE2';
$newQuantity           = 2;

try {
    $scheduledProductUpdate = $client->scheduleProductUpdate($sessionID, $subscriptionReference, 
    $newProductCode, $newPricingOptions, $newQuantity);
} catch (SoapFault $e) {
    echo "scheduleProductUpdate: " . $e->getMessage();
    exit;
}

var_dump("scheduleProductUpdate", $scheduledProductUpdate);

FAQ:

When is the scheduled update applied? At the next renewal - for both auto-renewals and manual renewals.

Is there a limit on how far in advance I can schedule an update? No specific time limit is enforced - the update remains scheduled until the next renewal or until explicitly removed.

How late in the billing cycle can an update be scheduled? At any point during the billing cycle, right up until the renewal.

Can I schedule changes to product, pricing options, and quantity at the same time? Yes. ProductCode, PricingOptions, and Quantity can be combined in a single scheduling call.

Can I schedule a quantity decrease? Yes. A quantity decrease is supported, but Quantity = 0 and negative values are not allowed and will return validation errors.

Are all pricing option types supported for scheduled subscription changes? Yes, with one exception: pay-per-usage (PAYPERUSAGE) pricing options are not supported.

Where can I see the scheduled update? In the GET subscription response under Future Events, and in the license history in the Control Panel and MyAccount after the update is applied.

Are shoppers notified when a subscription change is scheduled? No. Scheduling a subscription change does not trigger a notification to the shopper, however, an LCN will be sent to the vendor who can then decide to notify the shopper.

Does the renewal price reflect the scheduled changes? Yes. The GET renewal price APIs return pricing based on the scheduled changes.

Is the scheduled update applied if the subscription is renewed manually via MyAccount? Yes. The scheduled update is respected across all renewal paths.

Does an existing coupon still apply after a scheduled product change? Yes, provided the coupon is compatible with the new product. If the coupon is not compatible with the product being updated to, it will not be applied after the change.

Does an early renewal honor the scheduled changes? Yes. Early renewals respect the scheduled update - the subscription will renew with the new product, pricing options, and/or quantity as defined in the scheduled change.

 Is bulk scheduling across multiple subscriptions supported? No. Scheduling is performed per individual subscription reference. Bulk scheduling across multiple subscriptions in a single API call is not supported — the API is designed specifically for one subscription at a time.

Handle Connection Errors

Overview

If you want to catch and handle any errors encountered during the iFrame mounting process use the mountAsync method.

Use case

  1. Create a form with id="payment-form":

    <form type="post" id="payment-form">
     <div class="form-group">
       <label for="name" class="label control-label">Name</label>
       <input type="text" id="name" class="field form-control">
     </div>
     <button class="btn btn-primary" type="submit">Generate token</button>
    </form>
  2. Inside the form add an element with id="card-element". The form should now look like this:

    <form type="post" id="payment-form">
     <div class="form-group">
       <label for="name" class="label control-label">Name</label>
       <input type="text" id="name" class="field form-control">
     </div>
     <div id="card-element">
       <!-- A TCO IFRAME will be inserted here. -->
     </div>
     <button class="btn btn-primary" type="submit">Generate token</button>
    </form>
  3. Include the 2Pay.js drop-in payment client JavaScript.

    <script type="text/javascript" src="https://2pay-js.2checkout.com/v1/2pay.js"></script>
  4. Add the following configuration JavaScript to load the client and create the component.

    window.addEventListener('load', function() {
     // Initialize the JS Payments SDK client.
     let jsPaymentClient = new  TwoPayClient('YOUR_MERCHANT_CODE');
     
     // Create the component that will hold the card fields.
     let component = jsPaymentClient.components.create('card');
  5. Use the mountAsync method to catch any mounting errors and retry if needed.

    // Use mountAsync() to catch errors and retry if needed
    component.mountAsync('#card-element')
        .then(() => {
            console.log('Card component mounted successfully');
        })
        .catch((error) => {
            console.error('Mount failed, retrying after cleanup:', error);
            // Clean up the failed mount
            component.unmount();
    
            // Retry mounting
            component.mountAsync('#card-element')
                .then(() => {
                    console.log('Card component mounted successfully on retry');
                })
                .catch((retryError) => {
                    console.error('Retry failed:', retryError);
                });
        });

Demo

Place upgrade orders with InLine Cart

Overview

Upgrades a current subscription using the inline checkout.

 
The Checkout form will be prefilled with subscription's billing data.

Use case

  1. Add an HTML link or button in your page like the one below.
  2. Create a JavaScript click handler to execute the Inline Client desired methods.
  3. Use the TwoCoInlineCart.products.add({code, quantity, options}) method to prepare your catalog product.
  4. Set the license code as the subscription reference on the cart TwoCoInlineCart.cart.setSubscription('IMKNNVEY13').

     
    Make sure your parent subscription has upgrades available in Control Panel, for your current product.
  5. Set the upgrade flag on the cart TwoCoInlineCart.cart.setUpgrade(true).
  6. Use the TwoCoInlineCart.cart.checkout() method to show the cart on your page.

Sample request

HTML

<a href="#" class="btn btn-success" id="buy-button">Buy now!</a>

Javascript

window.document.getElementById('buy-button').addEventListener('click', function() {
  TwoCoInlineCart.products.add({
    code: "74B8E17CC0"
  });
  TwoCoInlineCart.cart.setSubscription('IMKNNVEY13');
  TwoCoInlineCart.billing.setEmail('john.doe@company.com');
  TwoCoInlineCart.cart.setUpgrade(true);
  TwoCoInlineCart.cart.checkout();
});

Upgrade partner subscription

Parameters

Parameters     Type/Description
sessionID     Required (String)
      Session identifier, output of the Login method. An exception is thrown for incorrect values.
Items     Object (Required)
  SubscriptionReference   String (Required)
      The 2Checkout unique subscription code.
  UpgradeProductCode   String (Required)
      Unique product identifier code of the product you wish the subscription to be upgraded to. 
  Quantity   String (Required)
      Defines the amount of product units to be renwed.
  PricingOptions   Object (Required)
    Code The 2Checkout unique pricing code.
ExtraDiscount     Object (Optional)
  Value   String
      Extra discount you offer to partner orders. 
  Type   String
      Possible values: FIXED or PERCENT.
ExtraMargin     Object (Optional)
  Value   String
      Extra margin you offer to partner orders.
  Type   String
      Possible values: FIXED or PERCENT.
ExternalReferenceNumber     String (optional)
      Set external reference identifiers for orders. Maximum 100 characters. 
Comment     String (Optional)
      Set comments on orders as needed.

Request

<?php
declare(strict_types=1);
class Configuration
{
    public const MERCHANT_CODE = 'MERCHANT';
    public const MERCHANT_KEY = 'SECRET_KEY';
    public const URL = 'http://api.avangate.local/rpc/6.0';
    public const ACTION = 'upgradePartnerSubscriptions';
    
    public const PAYLOAD =  <<<JSON
{
    "Items": [
        {
            "SubscriptionReference": "XYZ23GHUJK",
            "UpgradeProductCode": "AVANGATE",
            "Quantity": 5,
            "PricingOptions": [
                {
                    "Code": "option30p"
                },
                {
                    "Code": "option20p"
                }
            ]
        }
    ],
    "ExtraDiscount": {
        "Value": 10,
        "Type": "FIXED"
    },
    "ExtraMargin": {
        "Value": 10,
        "Type": "PERCENT"
    },
    "ExternalReferenceNumber": "EXT-007",
    "Comment": "API partner order for upgrade"
}
JSON;
 
}
class Client
{
    private const LOGIN_METHOD = 'login';
    private $calls = 1;
    private $sessionId;

    private function generateAuth(): array
    {
        $merchantCode = Configuration::MERCHANT_CODE;
        $key = Configuration::MERCHANT_KEY;
        $date = gmdate('Y-m-d H:i:s');
        $string = strlen($merchantCode) . $merchantCode . strlen($date) . $date;
        $algo = 'sha256';
        $hash = hash_hmac($algo, $string, $key);

        return compact('merchantCode', 'date', 'hash', 'algo');
    }

    public function login(string $url)
    {
        $payload = $this->generateAuth();
        $response = $this->call($url, array_values($payload), self::LOGIN_METHOD);
        $this->sessionId = $response['result'];
    }

    public function call(
        string $url = Configuration::URL,
        $payload = Configuration::PAYLOAD,
        string $action = Configuration::ACTION
    ): ?array {
        if (empty($this->sessionId) && $action !== self::LOGIN_METHOD) {
            $this->login($url);
        }
        if (is_string($payload)) {
            $payload = json_decode($payload, true);
        }
        if (!empty($this->sessionId)) {
            $payload = [$this->sessionId, $payload];
        }
        $payload = array_filter($payload);
        $request = json_encode([
            'jsonrpc' => '2.0',
            'method'  => $action,
            'params'  => $payload,
            'id'      => $this->calls++,
        ]);
        $curl = curl_init($url);
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($curl, CURLOPT_SSLVERSION, 0);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt(
            $curl,
            CURLOPT_HTTPHEADER,
            ['Content-Type: application/json', 'Accept: application/json', 'Cookie: XDEBUG_SESSION=PHPSTORM']
        );
        curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
        $response = curl_exec($curl);
        if (empty($response)) {
            die('Server unavailable');
        }
        echo $response . '</br>';

        return json_decode($response, true);;
    }
}

$client = new Client();
$result = $client->call();
var_dump($result);

Retrieve partner subscription upgrade price

Parameters

Parameters     Type/Description
sessionID     Required (String)
      Session identifier, output of the Login method. An exception is thrown for incorrect values.
Items     Object (Required)
  SubscriptionReference   String (Required)
      The 2Checkout unique subscription code.
  UpgradeProductCode   String (Required)
      Unique product identifier code of the product you wish the subscription to be upgraded to. 
  Quantity   String (Required)
      Defines the amount of product units to be renwed.
  PricingOptions   Object (Required)
    Code The 2Checkout unique pricing code.
ExtraDiscount     Object (Optional)
  Value   String
      Extra discount you offer to partner orders. 
  Type   String
      Possible values: FIXED or PERCENT.
ExtraMargin     Object (Optional)
  Value   String
      Extra margin you offer to partner orders.
  Type   String
      Possible values: FIXED or PERCENT.

Request

<?php
declare(strict_types=1);
class Configuration
{
    public const MERCHANT_CODE = 'MERCHANT';
    public const MERCHANT_KEY = 'SECRET_KEY';
    public const URL = 'http://api.avangate.local/rpc/6.0';
    public const ACTION = 'getPartnerSubscriptionsUpgradePrice';
    
    public const PAYLOAD =  <<<JSON
{
    "Items": [
        {
            "SubscriptionReference": "XYZ23GHUJK",
            "UpgradeProductCode": "Avangate",
            "Quantity": 5,
            "PricingOptions": [
                {
                    "Code": "option30p"
                },
                {
                    "Code": "option20p"
                }
            ]
        }
    ],
    "ExtraDiscount": {
        "Value": 10,
        "Type": "FIXED"
    },
    "ExtraMargin": {
        "Value": 10,
        "Type": "PERCENT"
    }
}
JSON;
 
}
class Client
{
    private const LOGIN_METHOD = 'login';
    private $calls = 1;
    private $sessionId;

    private function generateAuth(): array
    {
        $merchantCode = Configuration::MERCHANT_CODE;
        $key = Configuration::MERCHANT_KEY;
        $date = gmdate('Y-m-d H:i:s');
        $string = strlen($merchantCode) . $merchantCode . strlen($date) . $date;
        $algo = 'sha256';
        $hash = hash_hmac($algo, $string, $key);

        return compact('merchantCode', 'date', 'hash', 'algo');
    }

    public function login(string $url)
    {
        $payload = $this->generateAuth();
        $response = $this->call($url, array_values($payload), self::LOGIN_METHOD);
        $this->sessionId = $response['result'];
    }

    public function call(
        string $url = Configuration::URL,
        $payload = Configuration::PAYLOAD,
        string $action = Configuration::ACTION
    ): ?array {
        if (empty($this->sessionId) && $action !== self::LOGIN_METHOD) {
            $this->login($url);
        }
        if (is_string($payload)) {
            $payload = json_decode($payload, true);
        }
        if (!empty($this->sessionId)) {
            $payload = [$this->sessionId, $payload];
        }
        $payload = array_filter($payload);
        $request = json_encode([
            'jsonrpc' => '2.0',
            'method'  => $action,
            'params'  => $payload,
            'id'      => $this->calls++,
        ]);
        $curl = curl_init($url);
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($curl, CURLOPT_SSLVERSION, 0);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt(
            $curl,
            CURLOPT_HTTPHEADER,
            ['Content-Type: application/json', 'Accept: application/json', 'Cookie: XDEBUG_SESSION=PHPSTORM']
        );
        curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
        $response = curl_exec($curl);
        if (empty($response)) {
            die('Server unavailable');
        }
        echo $response . '</br>';

        return json_decode($response, true);;
    }
}

$client = new Client();
$result = $client->call();
var_dump($result);

Renew partner subscription

Parameters

Parameters     Type/Description
sessionID     Required (String)
      Session identifier, output of the Login method. An exception is thrown for incorrect values.
Items     Object (Required)
  SubscriptionReference   String (Required)
      The 2Checkout unique subscription code.
  Quantity   String (Required)
      Defines the amount of product units to be renwed.
  PricingOptions   Object (Required)
    Code The 2Checkout unique pricing code.
ExtraDiscount     Object (Optional)
  Value   String
      Extra discount you offer to partner orders. 
  Type   String
      Possible values: FIXED or PERCENT.
ExtraMargin     Object (Optional)
  Value   String
      Extra margin you offer to partner orders.
  Type   String
      Possible values: FIXED or PERCENT.
ExternalReferenceNumber     String (optional)
      Set external reference identifiers for orders. Maximum 100 characters. 
Comment     String (Optional)
      Set comments on orders as needed.

Request

<?php
declare(strict_types=1);
class Configuration
{
    public const MERCHANT_CODE = 'MERCHANT';
    public const MERCHANT_KEY = 'SECRET_KEY';
    public const URL = 'http://api.avangate.local/rpc/6.0';
    public const ACTION = 'renewPartnerSubscriptions';
    
    public const PAYLOAD =  <<<JSON
{
    "Items": [
        {
            "SubscriptionReference": "XYZ23GHUJK",
            "Quantity": 5,
            "PricingOptions": [
                {
                    "Code": "option30p"
                },
                {
                    "Code": "option20p"
                }
            ]
        }
    ],
    "ExtraDiscount": {
        "Value": 10,
        "Type": "FIXED"
    },
    "ExtraMargin": {
        "Value": 10,
        "Type": "PERCENT"
    },
    "ExternalReferenceNumber": "EXT-007",
    "Comment": "API partner order for renewal"
}
JSON;
 
}
class Client
{
    private const LOGIN_METHOD = 'login';
    private $calls = 1;
    private $sessionId;

    private function generateAuth(): array
    {
        $merchantCode = Configuration::MERCHANT_CODE;
        $key = Configuration::MERCHANT_KEY;
        $date = gmdate('Y-m-d H:i:s');
        $string = strlen($merchantCode) . $merchantCode . strlen($date) . $date;
        $algo = 'sha256';
        $hash = hash_hmac($algo, $string, $key);

        return compact('merchantCode', 'date', 'hash', 'algo');
    }

    public function login(string $url)
    {
        $payload = $this->generateAuth();
        $response = $this->call($url, array_values($payload), self::LOGIN_METHOD);
        $this->sessionId = $response['result'];
    }

    public function call(
        string $url = Configuration::URL,
        $payload = Configuration::PAYLOAD,
        string $action = Configuration::ACTION
    ): ?array {
        if (empty($this->sessionId) && $action !== self::LOGIN_METHOD) {
            $this->login($url);
        }
        if (is_string($payload)) {
            $payload = json_decode($payload, true);
        }
        if (!empty($this->sessionId)) {
            $payload = [$this->sessionId, $payload];
        }
        $payload = array_filter($payload);
        $request = json_encode([
            'jsonrpc' => '2.0',
            'method'  => $action,
            'params'  => $payload,
            'id'      => $this->calls++,
        ]);
        $curl = curl_init($url);
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
        curl_setopt($curl, CURLOPT_SSLVERSION, 0);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt(
            $curl,
            CURLOPT_HTTPHEADER,
            ['Content-Type: application/json', 'Accept: application/json', 'Cookie: XDEBUG_SESSION=PHPSTORM']
        );
        curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
        $response = curl_exec($curl);
        if (empty($response)) {
            die('Server unavailable');
        }
        echo $response . '</br>';

        return json_decode($response, true);;
    }
}

$client = new Client();
$result = $client->call();
var_dump($result);

Need help?

Do you have a question? If you didn’t find the answer you are looking for in our documentation, you can contact our Support teams for more information. If you have a technical issue or question, please contact us. We are happy to help.

Not yet a Verifone customer?

We’ll help you choose the right payment solution for your business, wherever you want to sell, in-person or online. Our team of experts will happily discuss your needs.

Verifone logo