Skip to main content

Enable recurring billing

Overview

Use the enableRecurringBilling method to switch on the automatic renewal system for a subscription that's manually renewable. 

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)

 

Unique, system-generated subscription identifier.

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 {
    $enabledSubscriptionRecurring = $client->enableRecurringBilling($sessionID, $subscriptionReferenceTest);
}
catch (SoapFault $e) {
    echo "enabledSubscriptionRecurring: " . $e->getMessage();
    exit;
}
var_dump("enabledSubscriptionRecurring", $enabledSubscriptionRecurring);

INS read receipt response

Overview

Notifications are sent by an HTTP POST request to the message URL that you specified on the INS Notifications tab.

The message parameters are passed as key => value pairs. Your message URLs should route to the script where you will be handling the message. You can listen for messages by simply setting up logic in your application to take action based on the message_type parameter that is passed in each message.

Message types

Currently, there are three types of messages sent using the Instant Notification System (INS).

1. Message Invoice is sent on triggers like order creation or invoice status change.

 {
    "sale_id":"1",
    "sale_date_placed":"1990-01-01 12:00:00",
    "recurring":1,
    "payment_type":"credit card",
    "list_currency":"USD",
    "fraud_status":"pass",
    "order_ref":"1",
    "order_no":"1",
    "vendor_id":"TESTVENDORID",
    "vendor_order_id":"",
    "invoice_id":"100000000000",
    "invoice_status":"approved",
    "invoice_list_amount":"100",
    "invoice_usd_amount":"100",
    "invoice_cust_amount":"100",
    "item_count":1,
    "auth_exp":"2022-01-01",
    "customer_first_name":"John",
    "customer_last_name":"Doe",
    "customer_name":"Jane Doe",
    "customer_email":"john.doe@test.com",
    "customer_phone":"",
    "customer_ip":"1.1.1.1",
    "customer_ip_country":null,
    "cust_currency":"USD",
    "bill_city":"TestCity",
    "bill_country":"NER",
    "bill_postal_code":"",
    "bill_state":"",
    "bill_street_address":"TestStreet",
    "bill_street_address2":"",
    "ship_status":"",
    "ship_tracking_number":"",
    "ship_name":"Doe John",
    "ship_street_address":"TestStreet",
    "ship_street_address2":"",
    "ship_city":"TestCity",
    "ship_state":"",
    "ship_postal_code":"",
    "ship_country":"NER",
    "message_id":1,
    "message_type":"INVOICE_STATUS_CHANGED",
    "message_description":"Invoice status changed",
    "timestamp":"2021-01-01 12:00:00 EEST",
    "key_count":1,
    "item_name_1":"Electronically Delivered Software",
    "item_id_1":"",
    "item_list_amount_1":"100",
    "item_usd_amount_1":"100",
    "item_cust_amount_1":"100",
    "item_type_1":"bill",
    "item_duration_1":"Forever",
    "item_recurrence_1":"1 Month",
    "item_rec_list_amount_1":"100",
    "item_rec_status_1":"live",
    "item_rec_date_next_1":"",
    "item_rec_install_billed_1":"1",
    "hash":"3B2EF87601E548597155C6751FFCCF76"
}

2.   Message Product is sent when a new product is created or an existing product is updated.

{
    "message_id":1,
    "message_type":"CATALOGUE_PRODUCT_CREATED",
    "message_description":"New catalogue product created",
    "timestamp":"2021-01-01 12:00:00 EEST",
    "key_count": 1,
    "avangate_id":"1",
    "enabled":true,
    "fulfillment":"NO_DELIVERY",
    "fulfillment_information":{
        "is_start_after_fulfillment":false,
        "is_electronic_code":false,
        "is_download_link":false,
        "is_backup_media":false,
        "is_download_insurance_service":false,
        "is_instant_delivery_thank_you_page":false,
        "is_display_in_partners_c_panel":false,
        "code_list":null,
        "backup_media":null,
        "product_file":null,
        "additional_information_by_email":null,
        "additional_information_email_translations":{
        },
        "additional_thank_you_page":null,
        "additional_thank_you_page_translations":{
        },
        "return_method":{
            "type":null,
            "url":null
        }
    },
    "generates_subscription":true,
    "gift_option":false,
    "product_group":null,
    "long_description":"",
    "platforms":{
        "0":{
            "id_platform":"1",
            "platform_name":"Linux",
            "category":"Desktop"
        }
    },
    "prices":{
        "name":"TEST's Price Configuration",
        "code":"TESTCODE",
        "default":true,
        "billing_countries":[
        ],
        "use_original_prices":false,
        "pricing_schema":"DYNAMIC",
        "price_type":"NET",
        "default_currency":{
            "id":"1",
            "code":"USD",
            "digitCode":"840",
            "label":"United States Dollar",
            "symbol":"$",
            "symbolPosition":"left",
            "decimalSeparator":".",
            "unitSeparator":",",
            "decimals":"2"
        },
        "prices":{
            "regular":{
                "0":{
                    "amount":100,
                    "currency":"USD",
                    "min_quantity":"1",
                    "max_quantity":"99999",
                    "option_codes":null
                }
            },
            "renewal":{
            }
        },
        "price_options":{
        }
    },
    "product_category":"TESTCATEGORY",
    "product_code":"TESTCODE",
    "product_images":null,
    "product_name":"TESTNAME",
    "product_type":"REGULAR",
    "product_version":"",
    "purchase_multiple_units":true,
    "shipping_class":null,
    "short_description":"",
    "subscription_information":{
        "deprecated_products":[
        ],
        "bundle_renewal_management":"GLOBAL",
        "billing_cycle":-1,
        "billing_cycle_units":"M",
        "is_one_time_fee":true,
        "contract_period":null,
        "usage_billing":7,
        "grace_period":null,
        "renewal_emails":{
            "type":"GLOBAL",
            "settings":{
                "manual_renewal":{
                    "before30_days":false,
                    "before15_days":false,
                    "before7_days":false,
                    "before1_day":false,
                    "on_expiration_date":false,
                    "after5_days":false,
                    "after15_days":false
                },
                "automatic_renewal":{
                    "before30_days":false,
                    "before15_days":false,
                    "before7_days":false,
                    "before1_day":true,
                    "on_expiration_date":true,
                    "after5_days":false,
                    "after15_days":false
                }
            }
        }
    },
    "trial_description":"",
    "trial_url":"",
    "tangible":false,
    "tangible_details":{
        "unit_details":[
        ],
        "fee":[
        ]
    },
    "hash":"435EA2BFAB983240CC27C5FC5D8323B4"
}

3. Message Proposal is sent when a proposal is created or updated. 

{
    "message_id":1,
    "message_type":"PROPOSAL_CREATED",
    "message_description":"Proposal created",
    "timestamp":"2021-01-01 12:00:00 EET",
    "key_count":1,
    "proposal_id":"1",
    "version":"1",
    "created_date":"2021-01-01 12:00:00",
    "updated_date":"2021-01-01 12:00:00",
    "created_by":"TEST",
    "updated_by":"TEST",
    "locked":"",
    "source":"",
    "content":"TEST CONTENT",
    "bill_to":"TEST BILL",
    "name":"TEST NAME",
    "tac":"TEST TAC",
    "type":"TEST TYPE",
    "sent_by":"TEST NAME 2",
    "links":"TEST LINK",
    "status":"PENDING",
    "expiration_date":"2022-01-01 12:00:00",
    "status_comment":"",
    "sell_to":"TEST NAME",
    "hash":"B87C32614A96FCE9C614C0721D19C3B0"
}

Validate response

Each notification message includes a hash computed using the secret word and secret key you set up in your Merchant Control Panel. The hash is returned on each message through the hash key containing the hash algorithm and the hash value, separated by a colon symbol.

Example: "hash":"SHA256:C7CE5C8C4355C3F3162D51530762A31BCFB700030AF3DF072744B5B817F63510"

According to the message, different parameters are required for the hash. The required parameters are concatenated for each type of message and the hash function is applied. The result is converted to uppercase. 

1. For message Invoice, the required parameters are the sale ID, the 2Checkout merchant ID, the invoice ID, and the secret word

PHP Example for Message Invoice

<?php

$invoiceDetails = $_POST;

$secretKey = 'EXAMPLE_SECRET_KEY';
$secretWord = 'EXAMPLE_SECRET_WORD';
$TCOVendorId = 123example_vendor_id;  // your 2checkout vendor id should be a number

$saleId = $invoiceDetails['sale_id'];
$invoiceId = $invoiceDetails['invoice_id'];
$hash = explode(':',$invoiceDetails['hash']); // index 0 is algorithm, index 1 is the hash

$parameters = [
    $saleId,
    $TCOVendorId,
    $invoiceId,
    $secretWord
];



$calculatedHash = strtoupper(hash_hmac($hash[0] ,implode($parameters),$secretKey));
if ($calculatedHash === $hash[1]) {
    http_response_code(200);
    echo true;
} else {
    http_response_code(400);
    echo "calculated hash: $calculatedHash \n";
    echo "received hash: $hash[1]";
}

?>

Node.JS (ES6) Example for Message Invoice

const crypto = require('crypto');
const merchantCode = '123example_vendor_id'; 
const secretWord = 'EXAMPLE_SECRET_WORD';
const secretKey = 'EXAMPLE_SECRET_KEY';

let saleId = request.params['sale_id'];
let invoiceId = request.params['invoice_id'];
let insHashArray = request.params['hash'].split(':');
let insAlgo = insHashArray[0];
let insHash = insHashArray[1];

let parameters = [
    saleId,
    merchantCode,
    invoiceId,
    secretWord
];

const hash = crypto.createHmac(insAlgo, secretKey)
               .update(parameters.join(''))
               .digest('hex');

console.log(hash.toUpperCase() === insHash);

Python Example for Message Invoice

import hmac

merchant_code = 'EXAMPLE_MERCHANT_CODE'
secret_word = 'EXAMPLE_SECRET_WORD'
secret_key = 'EXAMPLE_SECRET_KEY'
sale_id = param['sale_id']
invoice_id = param['invoice_id']
ins_hash_array = param['hash'].split(':')
ins_algo = ins_hash_array[0].replace('-', '_').lower();
ins_hash = ins_hash_array[1];

parameters = [
    sale_id,
    merchant_code,
    invoice_id,
    secret_word
]

hash_string = hmac.new(secret_key.encode('utf-8'), ''.join(parameters).encode('utf-8'), ins_algo).hexdigest().upper()

print(ins_hash == hash_string)

2. For message Product, the required parameters are the product code, the 2Checkout merchant ID, and the secret key

PHP Example for Message Product

<?php

$invoiceDetails = $_POST;

$secretKey = 'EXAMPLE_SECRET_KEY';
$TCOVendorId = 123example_vendor_id;  // your 2checkout vendor id should be a number

$productCode = $invoiceDetails['product_code'];
$hash = explode(':',$invoiceDetails['hash']); // index 0 is algorithm, index 1 is the hash

$parameters = [
    $productCode,
    $TCOVendorId,
    $secretKey
];



$calculatedHash = strtoupper(hash_hmac($hash[0] ,implode($parameters),$secretKey));
if ($calculatedHash === $hash[1]) {
    http_response_code(200);
    echo true;
} else {
    http_response_code(400);
    echo "calculated hash: $calculatedHash \n";
    echo "received hash: $hash[1]";
}

?>

Node.JS (ES6) Example for Message Product

const crypto = require('crypto');
const merchantCode = '123example_vendor_id'; 
const secretKey = 'EXAMPLE_SECRET_KEY';

let productCode = request.params[‘product_’code];
let insHashArray = request.params['hash'].split(':');
let insAlgo = insHashArray[0];
let insHash = insHashArray[1];

let parameters = [
    productCode,
    merchantCode,
    secretKey
];

const hash = crypto.createHmac(insAlgo, secretKey)
               .update(parameters.join(''))
               .digest('hex');

console.log(hash.toUpperCase() === insHash);

Python Example for Message Product

import hmac

merchant_code = 'EXAMPLE_MERCHANT_CODE'
secret_key = 'EXAMPLE_SECRET_KEY'
product_code = param[‘product_code’]
ins_hash_array = param['hash'].split(':')
ins_algo = ins_hash_array[0].replace('-', '_').lower();
ins_hash = ins_hash_array[1];

parameters = [
    product_code,
    merchant_code,
    secret_key
]

hash_string = hmac.new(secret_key.encode('utf-8'), ''.join(parameters).encode('utf-8'), ins_algo).hexdigest().upper()

print(ins_hash == hash_string)

3. For message Proposal, the required parameters are the proposal ID, the 2Checkout merchant ID, and the secret word.

PHP Example for Message Proposal

<?php

$invoiceDetails = $_POST;

$secretKey = '=B6gcTl(4t8@D3yUM!TP';
$secretWord = 'Mv#-Z*nb7U%qYJwc-tsb&f?JEyUP5p5WK4*txCfT@336CuwZrZkdqc&K$zEZqnBP';
$TCOVendorId = 250111206876;

$proposalId = $invoiceDetails['proposal_id'];
$hash = explode(':',$invoiceDetails['hash']); // index 0 is algo, index 1 is hash

$parameters = [
    $proposalId,
    $TCOVendorId,
    $secretWord
];



$calculatedHash = strtoupper(hash_hmac($hash[0] ,implode($parameters),$secretKey));
if ($calculatedHash === $hash[1]) {
    http_response_code(200);
    echo true;
} else {
    http_response_code(400);
    echo "calculated hash: $calculatedHash \n";
    echo "received hash: $hash[1]";
}

?>

Node.JS (ES6) Example for Message Proposal

const crypto = require('crypto');
const secretWord = 'AABBCCDDEEFF';
const 2COVendorId = 1;

let proposalId = request.params['proposal_id'];

let parameters = [
    proposalId,
    2COVendorId,
    secretWord
];

let hash = crypto.createHash('md5').update(parameters.join('')).digest();

console.log(hash.toUpperCase() === request.params['md5_hash']);

Python Example for Message Proposal

from urllib import request
from flask import Flask, jsonify, request, Request
from urllib.parse import urlencode, urldefrag
from werkzeug.datastructures import ImmutableOrderedMultiDict
import hashlib

class MyRequest(Request):
    parameter_storage_class = ImmutableOrderedMultiDict

class MyFlask(Flask):
    request_class = MyRequest

app = MyFlask(__name__)
def calculate_hash_string(payload_tuple_list):
    secretWord = 'AABBCCDDEEFF'
    2COVendorId = 1

    proposalId = payload_tuple_list['proposalId']

    parameters = [
        proposalId,
        2COVendorId,
        secretWord
    ]

    hash_string = hashlib.md5(''.join(parameters).encode('utf-8')).digest().upper()

    return hash_string

@app.route('/ins', methods=['POST'])
def ins():
    ins_payload_received = request.form
    return ins_payload_received['md5_hash'] === calculate_hash_string(ins_payload_received)

if __name__ == '__main__':
app.run()

Read receipt response

Currently, there are no required response values, so a basic response with HTTP 200 status will suffice.

3D Secure flow for API orders

Overview

3D Secure is a system designed to increase security of online transactions using cards by checking customer identities before allowing them to finalize purchase. 3D Secure works by redirecting your customers to pages provided by their banks, where they need to enter additional security tokens or password to trigger the completion of the charge.

By using 3D Secure, you get additional protection from liability for fraudulent card payments, with your customers having to go through an extra layer of authentication.

Introducing Dynamic 3D Secure via API

Starting with 2Checkout API 5.0, your orders placed via API are processed automatically through the Dynamic 3D Secure flow. Dynamic 3D Secure is mechanism that allows us to evaluate a transaction in real-time based on a range of rule parameters that are able to determine if 3D Secure should be enabled or not.

Based on specific filters set in our backend system, 3D Secure will be enabled or not on a transaction basis in real-time. The list of filters is includes:

  • Credit card issuing country
  • Billing country 
  • IP country 
  • Order amount

If one of these filters is not matching with the thresholds set in the 2Checkout system, 3D Secure will be enabled. Otherwise the transaction is considered to be safe and can go through without 3D Secure.

Availability

Placing orders via API with the 3D Secure flow is available starting with the version 5 of 2Checkout's API.

Benefits

Place orders via API starting with version 5, and let Dynamic 3D Secure mechanism bring you the following advantages:

  • Increased authorization rates – we measured and observed that in specific countries the use of 3D Secure could have an overwhelmingly positive impact (United Kingdom, Russia) while in other countries it has a negative impact (United States, China).
  • Mitigated fraud risks – 3D Secure significantly decreased the fraud rate for your incoming orders.
  • Less chargeback – the use of 3D Secure can reduce the number of chargebacks in some cases (e.g. reasons like fraud/not recognized) as customers are not allowed to open a chargeback with their bank.

How it works

For credit card orders placed starting with 2Checkout API 5.0, you need to pass through additional parameters that support the Dynamic 3D Secure flow.

Send the following parameters as part of the PaymentMethod object:

Parameters Description
Vendor3DSReturnURL Required (string)
  URL address to which customers are redirected after the 3DS details get validated by the bank and the order is successfully authorized.
Vendor3DSCancelURL Required (string)
  URL address to which customers are redirected if the 3DS details were not validated or the order could not be authorized.

 

Remove promotions translations

Request

<?php 

class Client
{
    protected static $merchantCode;
    protected static $loginDate;
    protected static $hash;
    protected static $baseUrl;
    protected static $callCount = 0;
    protected static $sessionId = '';

    protected static $client;

    public static function setCredentials($code, $key)
    {
        static::$merchantCode = $code;
        static::$loginDate = gmdate('Y-m-d H:i:s');
        static::$hash = hash_hmac('md5', strlen($code) . $code . strlen(static::$loginDate) . static::$loginDate, $key);
        static::$sessionId = static::login();
    }

    public static function setBaseUrl($url)
    {
        static::$baseUrl = $url;
    }

    public static function login()
    {
        $client = static::getClient();
        return $client->login(static::$merchantCode, static::$loginDate, static::$hash);
    }

    public static function __callStatic($name, $arguments = array())
    {
        $client = static::getClient();

        array_unshift($arguments, static::$sessionId);
        $response = call_user_func_array(array($client, $name), $arguments);

        return $response;
    }

    protected static function getClient()
    {
        $opts = array(
            'http'=> ['user_agent' => 'PHPSoapClient'],
            'ssl' => [
                'verify_peer' => false,
                'verify_peer_name' => false,
            ],
        );

        if (null === static::$client) {
            static::$client = new \SoapClient(static::$baseUrl . '?wsdl', [
                'location' => static::$baseUrl,
                'cache_wsdl' => WSDL_CACHE_NONE,
                'stream_context' => stream_context_create($opts),
            ]);
        }

        return static::$client;
    }
}

Client::setBaseUrl('https://api.avangate.com/soap/3.1/');
Client::setCredentials('YOUR_MERCHANT_CODE', 'YOUR_SECRET_KEY');
Client::login();

$promotionCode = 'YOUR_PROMOTION_CODE'; // code of the promotion that you want to update

$response = Client::deletePromotionTranslations($promotionCode); // remove all translations
var_dump($response);

Retrieve pricing configurations

Overview

Use the getPricingConfigurations method to extract information on the pricing configurations you set for a subscription plan/product.

Parameters

sessionID

Required (string)

 

Session identifier, the output of the Login method. Include sessionID into all your requests. Avangate throws an exception if the values are incorrect.  The sessionID expires in 10 minutes.

ProductCode

Required (string)

 

The editable code that you control at product-level, not the unique, system-generated product ID.

Response

PricingConfiguration

Array of objects

Request

<?php

$host   = "https://api.avangate.com";
$client = new SoapClient($host . "/soap/4.0/?wsdl", array(
    'location' => $host . "/soap/4.0/",
    "stream_context" => stream_context_create(array(
        'ssl' => array(
            'verify_peer' => false,
            'verify_peer_name' => false
        )
    ))
));


function hmac($key, $data)
{
    $b = 64; // byte length for md5
    if (strlen($key) > $b) {
        $key = pack("H*", md5($key));
    }
    
    $key    = str_pad($key, $b, chr(0x00));
    $ipad   = str_pad('', $b, chr(0x36));
    $opad   = str_pad('', $b, chr(0x5c));
    $k_ipad = $key ^ $ipad;
    $k_opad = $key ^ $opad;
    return md5($k_opad . pack("H*", md5($k_ipad . $data)));
}

$merchantCode = "YOURCODE123"; //your account's merchant code available in the 'System settings' area of the cPanel: https://secure.avangate.com/cpanel/account_settings.php
$key          = "SECRET_KEY"; //your account's secret key available in the 'System settings' area of the cPanel: https://secure.avangate.com/cpanel/account_settings.php
$now          = gmdate('Y-m-d H:i:s'); //date_default_timezone_set('UTC')

$string = strlen($merchantCode) . $merchantCode . strlen($now) . $now;
$hash   = hmac($key, $string);

try {
    $sessionID = $client->login($merchantCode, $now, $hash);
}

catch (SoapFault $e) {
    echo "Authentication: " . $e->getMessage();
    exit;
}

$ProductCode = 'AAA4643116';

try {
    $ProductPricingConfigurations = $client->getPricingConfigurations($sessionID, $ProductCode);
}

catch (SoapFault $e) {
    echo "Pricing Configurations: " . $e->getMessage();
    exit;
}

var_dump("Pricing Configurations", $ProductPricingConfigurations);


?>

Retrieve recommended upsell campaign

Overview

Use the getRecommendedUpsellCampaign method via JSON-RPC API 6.0 to find a campaign for the product code and the other sent filters.

Request Parameters

Parameter Name Type Required/Optional Description
SessionId String Required

Unique 2Checkout session ID code.

 

ProductCode String Required

The primary product code.

Quantity Integer Optional

The product quantity.

PriceOptions String Optional

The price options for the primary product.

EnabledForRenewals Boolean Optional

Returns only upsell campaigns that are enabled (or not) for renewals.

Request Example

<?php

require('PATH_TO_AUTH');

$productCode = 'upsell_module_po';
$quantity = 13;
$priceOptions = 'option1,module_scale_po2=5';
$enabledForRenewals = true;

$jsonRpcRequest = new stdClass();
$jsonRpcRequest->jsonrpc = '2.0';
$jsonRpcRequest->method = 'getRecommendedUpsellCampaign';
$jsonRpcRequest->params = [$sessionID, $productCode, $quantity, $priceOptions, $enabledForRenewals];
$jsonRpcRequest->id = $i++;

$resp = callRPC($jsonRpcRequest, $host);
$response = json_encode($resp, JSON_PRETTY_PRINT);
echo PHP_EOL . 'getRecommendedUpsellCampaign response:' . PHP_EOL . var_export($resp, true) . PHP_EOL;

Response

Parameters Type Description

UpSell

Object

Object containing information related to the upsell campaigns, including product information and discount settings.

Update reseller information

Overview

Use this method to update the details for an existing reseller entity in the Avangate platform.

Note: Updating the details of a reseller does not impact the reseller information already attached to existing partner orders. Let's assume that you added Reseller 1 to Order 1, and then update Reseller 1 changing the company name. Reseller 1 for Order 1 will continue to feature the old Reseller 1 information. To swap it for the new details, add the reseller to the order again using setOrderReseller.

Requirements

Parameters

Parameter Type/Description
sessionID Required (string)
  Session identifier, which is the output of the Login method. An exception will be thrown if the values are incorrect.
Reseller Required (object)

Response

Parameter Type/Description
Result Boolean

Request

<?php

require('PATH_TO_AUTH'); // Authentication example: https://knowledgecenter.avangate.com/Integration/Channel_Manager_API/SOAP/02Authentication
require('PATH_TO_setPartner'); // setPartner example: https://knowledgecenter.avangate.com/Integration/Channel_Manager_API/SOAP/06Reference/Partner/00Set_partner

$Reseller = new stdClass(); // Reseller details that will be updated
$Reseller ->ResellerCode = 'YOUR_RESELLER_CODE'; // Reseller code identifying the reseller whose details are updated. Must belong to an existing reseller.
$Reseller->Company = 'NewCompanyName';
$Reseller->FirstName = ' NewFirstName';
$Reseller->LastName = 'NewLastName';
$Reseller->Email = 'Newemail@example.com';
$Reseller->Phone = '123333344';
$Reseller->Fax = '12234567';
$Reseller->Country = 'US';
$Reseller->State = 'California';
$Reseller->City = 'LA';
$Reseller->Address = 'Address';
$Reseller->PostalCode = '90210';

try {
    $UpdatedReseller= $client->updateReseller($sessionID, $Reseller);
} catch (SoapFault $e) {
    Echo "UpdatedReseller: " . $e->getMessage();
    exit;
}
var_dump ("UpdatedReseller ", $UpdatedReseller);

//If the reseller is attached to an existing order you need to reassign the updated reseller details to the order, as the info won't be refreshed automatically.
try {
    $Reseller= $client->getOrderReseller ($sessionID, $RefNo);
} catch (SoapFault $e) {
    Echo "Reseller: " . $e->getMessage();
    exit;
}
var_dump ("Reseller ", $Reseller);

$ResellerCodeNew = $Reseller->ResellerCode;
try {
    $AddedReseller= $client->setOrderReseller ($sessionID, $RefNo, $ResellerCodeNew);
} catch (SoapFault $e) {
    Echo "orderReseller: " . $e->getMessage();
    exit;
}
var_dump ("orderReseller ", $AddedReseller);

Place an order with WeChat Pay

Overview

Use the placeOrder method to create an order and collect the payment from WeChat.

Requirements

WeChat Pay is available only for orders with a minimum value of 0.01 USD, placed by shoppers in China or Hong Kong and using one of the supported currencies. You are required to include the following text when using Avangate API and to make it visible for your customers in the ordering interface. 

Order processed by Avangate, authorized reseller and merchant of the products and services offered within this store. 

Supported currencies

  • CNY
  • USD
  • HKD

Workflow

  1. Shoppers select WeChat as payment option in the interface you provide to them.
  2. Create the order object. Use WE_CHAT_PAY as the type of the PaymentDetails object, and include ReturnURL and CancelURL.
  3. Use the placeOrder method to send the data to Avangate.
  4. Once you place the order, Avangate logs it into the system. At this point in time, the status of the order is PENDING.
  5. Avangate returns an Order object as the output of the placeOrder method. 
  6. Use the PaymentMethod object to create a redirect URL for the shoppers, concatenating the values of the Href and avng8apitoken parameters. Here's an example of the redirect URL:
    https://api.avangate.com/4.0/scripts/we_chat_pay/authorize/?avng8apitoken=1abc7fd72d008428
  7. After being redirected to WeChat Pay, shoppers need to scan the QR code provided, using the WeChat smartphone app.
  8. After customers enter their payment password, WeChat notifies Avangate if the payment is approved, and the status of the order becomes COMPLETE.
  9. Shoppers are redirected to the RedirectURL from the Order information object. In case the payment fails, shoppers are redirected to the CancelURL.

Parameters

Parameters Type/Description

sessionID

Required (string)

 

Session identifier, the output of the Login method. Include sessionID into all your requests. Avangate 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.

To place an order with WeChat, use WE_CHAT_PAY as the type of the PaymentDetails object and provide a ReturnURL and a CancelURL as part of the PaymentMethod object. See code sample. 

Response

Order information

Object

Request

<?php

// authentication script: https://knowledgecenter.avangate.com/Integration/SOAP_API/API_4.0/02Authentication

require ('PATH_TO_AUTH');

$Order = new stdClass();
$Order->RefNo = NULL;
$Order->Currency = 'cny';
$Order->Country = 'cn';
$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->Items[0]->AdditionalFields = NULL;
$Order->BillingDetails = new stdClass();
$Order->BillingDetails->FirstName = 'FirstName';
$Order->BillingDetails->LastName = 'LastName';
$Order->BillingDetails->CountryCode = 'CN';
$Order->BillingDetails->State = 'State Example';
$Order->BillingDetails->City = 'City Example';
$Order->BillingDetails->Address1 = 'Address example';
$Order->BillingDetails->Address2 = NULL;
$Order->BillingDetails->Zip = '12345';
$Order->BillingDetails->Email = 'email@address.com';
$Order->BillingDetails->Phone = NULL;
$Order->BillingDetails->Company = NULL;
$Order->PaymentDetails = new stdClass ();
$Order->PaymentDetails->Type = 'WE_CHAT_PAY';
$Order->PaymentDetails->Currency = 'cny';
$Order->PaymentDetails->PaymentMethod = new stdClass ();
$Order->PaymentDetails->CustomerIP = '91.220.121.21';
$Order->PaymentDetails->PaymentMethod->ReturnURL = 'YOUR_RETURN_URL';
$Order->PaymentDetails->PaymentMethod->CancelURL= 'YOUR_CANCEL_URL';

try {
   $newOrder = $client->placeOrder($sessionID, $Order);
}
catch (SoapFault $e) {
    echo "newOrder: " . $e->getMessage();
    exit;
}

$wechatredirect = $newOrder->PaymentDetails->PaymentMethod->Authorize->Href."/?avng8apitoken=".$newOrder->PaymentDetails->PaymentMethod->Authorize->Params->avng8apitoken;

header('Location:' . $wechatredirect);
?>

Refund an order

Overview

Refund a sale made in 2Checkout via the issueRefund API method. Depending on your business needs, you can refund only one sale item, the entire order amount, or a partial amount from the total order.

Requirements

The payment for the refundable order needs to be collected.

You cannot issue a refund for an amount higher than the total order amount.

Parameters

Parameters Type/Description
RefNo

String / Required

The order reference number of the sale for which the refund is issued. Example: '721924012'.

Amount

Double / Required

Refundable amount. Required as a supplementary check for partial refunds. Example: '26.00'.

Comment

String / Optional

Comments are displayed to customers in the refund confirmation they receive. Example: 'Let us know if you are satisfied with the refund process'. 

Reason

String / Required

In case you have custom refund reasons defined on your account, send one of the reasons. If not, send one of the platform defined reasons. Read more about 2Checkout refund reasons.

Example: 'Unwanted auto-renewal'.

Items

Array / Required only for partial refunds

In case you issue a partial refund, send the array with the information below.

  ProductCode 

String / Required

Send the product code belonging to the products to be refunded. The product code is available at product level, in the Information tab.

  Quantity

Integer / Required

Quantity to be refunded. Send only positive values.

  Amount

Double / Required

Total amount of the refunded line item, not the unit amount.

 

 

Convert a trial

Overview

Use the convertTrial method to convert a trial to a paid subscription. In the eventuality of a conversion failure, you can use convertTrial again for the same trial subscription only after you let 24 hours pass since the initial attempt. The 2Checkout system attempts to automatically convert trials before they expire to full subscriptions, unless you made an attempt that failed less than 24 hours before the scheduled expiration deadline.

In case the trial conversion fails due to a transaction issue, the 2Checkout system sends unfinished payment follow-up emails to customers, provided that you set up lead management for your account.

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)

 

Unique, system-generated subscription identifier of the trial that you convert to a paid subscription. The unique identifier from the 2Checkout system:

  • Must belong to an active trial subscription with the recurring billing system (auto-renewal) enabled.
  • The initial order placed to access the trial subscription must be finalized (status Finished).

Note: This method does not work for cancelled and/or expired trial subscriptions.

 

2Checkout charges customers using the payment data attached to the trial subscription. In the case of credit/debit cards, if customers update their payment information in myAccount or if you update these details on behalf of your subscribers, the 2Checkout system uses the latest card info provided to charge subscription renewals.

ExtendSubscriptionFromPaymentDate

Optional (boolean)

 

true = Set the moment of the conversion as the start date of the full subscription. 

Example: A 7 day trial purchased on October 29 for a monthly subscription converted on October 30 with $ExtendSubscriptionFromPaymentDate = true; features the following Billing cycle expiration: Nov 30, 2013 and 2Checkout scraps the initial trial expiration date November 5.

 

false = Set initial trial expiration deadline as the fhe full subscription start date. 

Example: A 10 day trial purchased on October 29 for a monthly subscription converted on October 30 with $ExtendSubscriptionFromPaymentDate = false; features the following Billing cycle expiration: December 9, with the first month period of the subscription added to the trial lifetime stretching until November 8.

 

Can be NULL. If not sent, the default value is false.

Response

Boolean

true or false depending on whether the changes were successful or not.

Request


<?php
$host   = "https://api.2checkout.com";
$client = new SoapClient($host . "/soap/3.0/?wsdl", array(
    'location' => $host . "/soap/3.0/",
    "stream_context" => stream_context_create(array(
        'ssl' => array(
            'verify_peer' => false,
            'verify_peer_name' => false
        )
    ))
));

function hmac($key, $data)
{
    $b = 64; // byte length for md5
    if (strlen($key) > $b) {
        $key = pack("H*", md5($key));
    }
    
    $key    = str_pad($key, $b, chr(0x00));
    $ipad   = str_pad('', $b, chr(0x36));
    $opad   = str_pad('', $b, chr(0x5c));
    $k_ipad = $key ^ $ipad;
    $k_opad = $key ^ $opad;
    return md5($k_opad . pack("H*", md5($k_ipad . $data)));
}
$merchantCode = "YOUR_MERCHANT_CODE";// your account's merchant code available in the 'System settings' area of the cPanel: https://secure.2checkout.com/cpanel/account_settings.php
$key = "YOUR_SECRET_KEY";// your account's secret key available in the 'System settings' area of the cPanel: https://secure.2checkout.com/cpanel/account_settings.php
$now          = gmdate('Y-m-d H:i:s'); //date_default_timezone_set('UTC')
$string = strlen($merchantCode) . $merchantCode . strlen($now) . $now;
$hash   = hmac($key, $string);
try {
    $sessionID = $client->login($merchantCode, $now, $hash);
}
catch (SoapFault $e) {
    echo "Authentication: " . $e->getMessage();
    exit;
}
$SubscriptionReference = '30E47F8699';
$ExtendSubscriptionFromPaymentDate = true; //false can also be used if you want the subscription start date to be the moment when the trial was set to initially expire.
try {
    $convertedTrial = $client->convertTrial($sessionID, $SubscriptionReference, $ExtendSubscriptionFromPaymentDate);
}
catch (SoapFault $e) {
    echo "convertedTrial: " . $e->getMessage();
    exit;
}
var_dump("convertedTrial", $convertedTrial);

 

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