Skip to main content

Subscription change deal

Subscription change deal

Last updated: 02-Apr-2021
Rate this article:

Overview

Use the changeDeal method to change the existing deal for a given subscription and operate the amendment order necessary to transition to the proposed deal immediately. The amendment order will use the due now prices returned by the getDealInfo method when called with the same relevant request parameters.

Request parameters

Parameter name Type Required/Optional Description

Currency

String

Required

The currency.

Country

String

Required

The country.

Language

String

Required

The language.

CustomerIp

String

Optional

The customer's IP address.

Items

Array

Required

Each item corresponds to a subscription.

 Items.DealDate

String

Required

The date when the deal is set to come into effect.

Items.SubscriptionReference

String

Required

The subscription code.

Items.ProductCode

String

Required

The product code.

Items.Quantity

String

Required

The product quantity.

Items.DealPriceScenario

String

Required

The upgrade scenario to be applied. Must be one of: using_last_order_price, using_last_product_price, price_total, product_price_difference.

Items.DealSubscriptionScenario

String

Required

The scenario for price calculation. Must be one of prolong, does_not_affect, disable_existing.

Items.PriceOptions

Array

optional

The array of price options.

Items.PriceOptions.Code

String

Required

The price options group code.

Items.PriceOptions.Options

Array

Required

The list of price option value (if the group is of type interval) or the price option code (otherwise).

Items.Price

Object

Required

The product price.

Items.Price.Amount

Float

Required

The actual numeric amount.

Items.Price.Type

String

Required

Describes if the price type is catalog or custom. Can be only CUSTOM.

Items.Price.AmountType

String

Required

Describes if the price is NET or GROSS. Can be on of NET, GROSS.

Items.SubscriptionCustomSettings

Object

Required

Product license custom settings.

Items.SubscriptionCustomSettings.CycleLength

Int

Required

The length of a single billing cycle.

Items.SubscriptionCustomSettings.CycleUnit

String

Required

The unit of a single billing cycle. Can be one of MONTH, DAY.

Items.SubscriptionCustomSettings.CycleAmount

Float

Required

The price of a single billing cycle.

Items.SubscriptionCustomSettings.CycleAmountType

String

Required

Describes the price type. Can be one of NET, GROSS.

Items.SubscriptionCustomSettings.ContractLength

Int

Required

The number of billing cycles contained in a single contract.

Items.SubscriptionCustomSettings.ClientDealAutoRenewal

Boolean

Optional

CDAR value (default false).

Items.SubscriptionCustomSettings.MerchantDealAutoRenewal

Boolean

Optional

MDAR value (default false).

BillingDetails

Object

required

The billing details.

BillingDetails.FirstName

String

Required

The first name.

BillingDetails.LastName

String

Required

The last name.

BillingDetails.CountryCode

String

Required

The country code. Must be one of the seller's associated country codes.

BillingDetails.State

String

Optional

Required only if the business model requires it.

BillingDetails.City

String

Required

The city name.

BillingDetails.Address1

String

Required

The address.

BillingDetails.Zip

String

Required

The zip code.

BillingDetails.Email

String

Required

The email address.

BillingDetails.Phone

String

Required

The phone number.

BillingDetails.Company

String

Required

The company's legal name.

BillingDetails.FiscalCode

String

Required

The fiscal code.

DeliveryDetails

Object

Required

The delivery details.

DeliveryDetails.FirstName

String

Required

The first name.

DeliveryDetails.LastName

String

Required

The last name.

DeliveryDetails.CountryCode

String

Required

The country code. Must be one of the seller's associated country codes.

DeliveryDetails.State

String

Optional

Required only if the business model requires it.

DeliveryDetails.City

String

Required

The city name.

DeliveryDetails.Address1

String

Required

The address.

DeliveryDetails.Zip

String

Required

The zip code.

DeliveryDetails.Email

String

Required

The email address.

DeliveryDetails.Phone

String

Required

The phone number.

DeliveryDetails.Company

String

Required

The company's legal name.

PaymentDetails

Object

Optional

The payment details.

PaymentDetails.Type

String

Required

Payment type. Can be CC (credit card) or EES_TOKEN_PAYMENT (2payJs token).

PaymentDetails.Currency

String

Required

Payment currency code.

PaymentDetails. CustomerIP

String

Required

Payment customer IP.

PaymentDetails.PaymentMethod

Object

Required

The payment method information.

PaymentDetails.PaymentMethod.EesToken

String

Optional

EES token (required when payment type is EES_TOKEN_PAYMENT).

PaymentDetails.PaymentMethod.CardNumber

Int

Optional

CC number (required when payment type is CC).

PaymentDetails.PaymentMethod.CardType

String

Optional

CC type (ex: VISA, MC; required when payment type is CC).

PaymentDetails.PaymentMethod.ExpirationYear

Int

Optional

4 digits CC expiration year (required when payment type is CC).

PaymentDetails.PaymentMethod.ExpirationMonth

Int

Optional

CC expiration month (required when payment type is CC).

PaymentDetails.PaymentMethod.CCID

String

Optional

CC CVV value (required when payment type is CC).

PaymentDetails.PaymentMethod.HolderName

String

Optional

CC holder name.

PaymentDetails.PaymentMethod.Vendor3DSReturnURL

String

Required

Merchant 3DS return URL.

PaymentDetails.PaymentMethod.Vendor3DSCancelURL

String

Required

Merchant 3DS cancel URL.

PaymentDetails.PaymentMethod.RecurringEnabled

Boolean

Optional

Flag to enable recurring on the new license when set true.

ExtraInformation

Object

Optional

Order extra information.

ExtraInformation.ProposalId

String

Optional

Related proposal object ID.

ExtraInformation.PurchaseOrderDownloadLink

String

Optional

PO Download link.

ExtraInformation.AMEmailB2B

String

Optional

AM email for B2B.

ExtraInformation.RetryFailedPaymentLink

String

Optional

Retry failed payment link.

Request example

<?php
declare(strict_types=1);
class Configuration
{
    public const MERCHANT_CODE = '1234554321';
    public const MERCHANT_KEY = 'D+~=z5R+R4])4D5&p56%';
    public const URL = 'http://api.avangate.local/rpc/6.0';
    public const ACTION = 'getDealInfo';
    //array or JSON
    public const PAYLOAD = <<<JSON
{
    "Currency": "usd",
    "Country": "us",
    "Language": "en",
    "CustomerIp": "91.220.121.21",
    "Source": "salesforce_cpq",
    "Items": [
        {
            "DealDate": "2021-03-18 13:36:47",
            "SubscriptionReference": "GUC9PFSIH8",
            "ProductCode": "PAV2019",
            "Quantity": 1,
            "DealPriceScenario": "using_last_order_price",
            "DealSubscriptionScenario": "prolong",
            "Price": {
                "Amount": 50,
                "Type": "CUSTOM",
                "AmountType": "GROSS"
            },
            "PriceOptions": [
                {
                    "Code": "interval_scale_grp1",
                    "Options": [
                        "25"
                    ]
                },
                {
                    "Code": "OPTGRP1",
                    "Options": [
                        "OptGrp1Code1"
                    ]
                }
            ],
            "SubscriptionCustomSettings": {
                "CycleLength": 1,
                "CycleUnit": "MONTH",
                "CycleAmount": 50,
                "CycleAmountType": "GROSS",
                "ContractLength": 12,
                "ClientDealAutoRenewal": true,
                "MerchantDealAutoRenewal": true
            }
        }
    ],
    "BillingDetails": {
        "FirstName": "Donald",
        "LastName": "Wilson",
        "CountryCode": "us",
        "State": "Texas",
        "City": "Dallas",
        "Address1": "4519 BlueBridge Road",
        "Zip": "02199",
        "Email": "dwilson@test.com",
        "Phone": "6172938133",
        "Company": "Integra Wealth",
        "FiscalCode": "85421564"
    },
    "DeliveryDetails": {
        "FirstName": "Gerard",
        "LastName": "Butler",
        "CountryCode": "us",
        "State": "Texas",
        "City": "Austin",
        "Address1": "2033 Nuzum Court",
        "Zip": "14216",
        "Email": "gerard.butler@integrawealth.net",
        "Phone": "7165708136",
        "Company": "Integra Wealth"
    },
    "PaymentDetails": {
        "Type": "EES_TOKEN_PAYMENT",
        "Currency": "usd",
        "CustomerIP": "91.220.121.21",
        "PaymentMethod": {
            "EesToken": "7886eebb-0aa0-482c-8636-28394e2b714d",
            "RecurringEnabled": true
        }
    },

    "ExtraInformation": {
       "ProposalId": "1de36a0a-a7b6-4cb7-9de5-34c802e4243b",
       "PurchaseOrderDownloadLink": "http://secure.avangate.local/proposal/po/342322/dl",
       "AMEmailB2B": "test@email.org",
       "RetryFailedPaymentLink": "http://secure.avangate.local/proposal/po/342322/retry?ref=[REFNO]"
    }
}
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;
        $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, $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

The changeDeal method has (almost) the same response parameters as the getDealInfo method, plus the deal order details returned under the DealOrder key. These order details have the same structure as any placeOrder  API method response (see here).

[
    {
        "SubscriptionReference": "GUC9PFSIH8",
        "DealPriceScenario": "using_last_order_price",
        "DealSubscriptionScenario": "prolong",
        "DealDate": "2021-03-18 13:36:47",
        "DealDueNowPriceNet": 47.06,
        "DealDueNowPriceGross": 50,
        "DealTaxAmount": 2.94,
        "DealTaxPercent": 6.25,
        "CurrentInfo": {
            "ProductCode": "BKG20193",
            "ProductName": "Backgammon 2019.3",
            "ProductDescription": "",
            "BillingPriceNet": 45,
            "UnitBillingPriceNet": 45,
            "BillingPriceGross": 47.81,
            "UnitBillingPriceGross": 47.81,
            "NoOfBillingCycles": 13,
            "CurrentBillingCycle": 1,
            "PayedBillingCycles": 1,
            "RemainingBillingCycles": 11,
            "CurrentBillingCycleEndDate": "2021-03-15 11:35:02",
            "ClientDealAutoRenewal": false,
            "MerchantDealAutoRenewal": false,
            "Quantity": 1,
            "CurrencyCode": "usd",
            "TaxAmount": 2.81,
            "TaxPercent": 6.25,
            "BillingCyclesFrequency": 1,
            "BillingCycleFrequencyUnit": "MONTH",
            "ContractLength": 12,
            "ContractLengthUnit": "MONTH",
            "ProductOptions": []
        },
        "NewDealInfo": {
            "ProductCode": "PAV2019",
            "ProductName": "Pipera AntiVirus 2019",
            "ProductDescription": "",
            "BillingPriceNet": 47.06,
            "BillingPriceGross": 50,
            "NoOfBillingCycles": 12,
            "CurrentBillingCycle": 1,
            "PayedBillingCycles": 0,
            "RemainingBillingCycles": 12,
            "CurrentBillingCycleEndDate": "2021-04-18 13:36:47",
            "TaxAmount": 2.94,
            "TaxPercent": 6.25,
            "CurrencyCode": "usd",
            "BillingCyclesFrequency": 1,
            "BillingCycleFrequencyUnit": "MONTH",
            "ContractLength": 12,
            "ContractLengthUnit": "MONTH",
            "ProductOptions": [
                {
                    "Code": "interval_scale_grp1",
                    "Options": [
                        "25"
                    ]
                },
                {
                    "Code": "OPTGRP1",
                    "Options": [
                        "OptGrp1Code1"
                    ]
                }
            ]
        },
        "TotalsDealInfo": {
            "DealsNumber": 0,
            "ContractsNumber": 1,
            "PaidBillingCycles": 1,
            "ElapsedBillingCycles": 1
        },
        "DealOrder": {
            "RefNo": "11591805",
            "OrderNo": 0,
            "ExternalReference": null,
            "ShopperRefNo": null,
            "Status": "AUTHRECEIVED",
            "ApproveStatus": "WAITING",
            "VendorApproveStatus": "OK",
            "MerchantCode": "120000589445",
            "Language": "en",
            "OrderDate": "2021-02-15 13:39:29",
            "FinishDate": null,
            "Source": null,
            "Affiliate": {
                "AffiliateCode": null,
                "AffiliateSource": null,
                "AffiliateName": null,
                "AffiliateUrl": null
            },
            "HasShipping": true,
            "BillingDetails": {
                "FiscalCode": "85421564",
                "TaxOffice": null,
                "Phone": "6172938133",
                "FirstName": "Donald",
                "LastName": "Wilson",
                "Company": "Integra Wealth",
                "Email": "dwilson@test.com",
                "Address1": "4519 BlueBridge Road",
                "Address2": null,
                "City": "Dallas",
                "Zip": "02199",
                "CountryCode": "us",
                "State": "Texas"
            },
            "DeliveryDetails": {
                "Phone": "7165708136",
                "FirstName": "Gerard",
                "LastName": "Butler",
                "Company": "Integra Wealth",
                "Email": "gerard.butler@integrawealth.net",
                "Address1": "2033 Nuzum Court",
                "Address2": null,
                "City": "Austin",
                "Zip": "14216",
                "CountryCode": "us",
                "State": "Texas"
            },
            "PaymentDetails": {
                "Type": "CC",
                "Currency": "usd",
                "PaymentMethod": {
                    "FirstDigits": "4111",
                    "LastDigits": "1111",
                    "CardType": "visa",
                    "RecurringEnabled": true,
                    "Vendor3DSReturnURL": null,
                    "Vendor3DSCancelURL": null,
                    "InstallmentsNumber": null
                },
                "CustomerIP": "91.220.121.21"
            },
            "DeliveryInformation": {
                "ShippingMethod": {
                    "Code": null,
                    "TrackingUrl": null,
                    "TrackingNumber": null,
                    "Comment": null
                }
            },
            "CustomerDetails": null,
            "Origin": "API",
            "AvangateCommission": 4.4,
            "OrderFlow": "REGULAR",
            "GiftDetails": null,
            "PODetails": null,
            "ExtraInformation": {
                "RetryFailedPaymentLink": "http:\/\/secure.avangate.local\/proposal\/po\/342322\/retry?ref=11591805",
                "ProposalId": "1de36a0a-a7b6-4cb7-9de5-34c802e4243b",
                "PurchaseOrderDownloadLink": "http:\/\/secure.avangate.local\/proposal\/po\/342322\/dl",
                "B2B": true,
                "AMEmailB2B": "test@email.org"
            },
            "PartnerCode": null,
            "PartnerMargin": null,
            "PartnerMarginPercent": null,
            "ExtraMargin": null,
            "ExtraMarginPercent": null,
            "ExtraDiscount": null,
            "ExtraDiscountPercent": null,
            "LocalTime": null,
            "TestOrder": false,
            "FxRate": 0.76357124584292,
            "FxMarkup": 10.456,
            "PayoutCurrency": "EUR",
            "DeliveryFinalized": false,
            "Errors": null,
            "Items": [
                {
                    "ProductDetails": {
                        "Name": "Pipera AntiVirus 2019",
                        "ShortDescription": "",
                        "Tangible": false,
                        "IsDynamic": false,
                        "ExtraInfo": null,
                        "RenewalStatus": false,
                        "Subscriptions": null,
                        "DeliveryInformation": {
                            "Delivery": "NO_DELIVERY",
                            "DownloadFile": null,
                            "DeliveryDescription": "",
                            "CodesDescription": "",
                            "Codes": []
                        }
                    },
                    "PriceOptions": [
                        {
                            "Code": "OPTGRP1",
                            "Name": "OptGrp1",
                            "Required": false,
                            "Options": [
                                {
                                    "Name": "2 users",
                                    "Value": "OptGrp1Code1",
                                    "Surcharge": "5.00"
                                }
                            ]
                        },
                        {
                            "Code": "interval_scale_grp1",
                            "Name": "Interval scale group1",
                            "Required": false,
                            "Options": [
                                {
                                    "Name": "Interval scale group1: 25",
                                    "Value": "interval_scale_grp1=25",
                                    "Surcharge": "125.00"
                                }
                            ]
                        }
                    ],
                    "Price": {
                        "UnitNetPrice": 47.06,
                        "UnitGrossPrice": 50,
                        "UnitVAT": 2.94,
                        "UnitDiscount": 0,
                        "UnitNetDiscountedPrice": 47.06,
                        "UnitGrossDiscountedPrice": 50,
                        "UnitAffiliateCommission": 0,
                        "ItemUnitNetPrice": null,
                        "ItemUnitGrossPrice": null,
                        "ItemNetPrice": null,
                        "ItemGrossPrice": null,
                        "VATPercent": 6.25,
                        "HandlingFeeNetPrice": 0,
                        "HandlingFeeGrossPrice": 0,
                        "Currency": "usd",
                        "NetPrice": 47.06,
                        "GrossPrice": 50,
                        "NetDiscountedPrice": 47.06,
                        "GrossDiscountedPrice": 50,
                        "Discount": 0,
                        "VAT": 2.94,
                        "AffiliateCommission": 0
                    },
                    "LineItemReference": "f703af791bca619bbd42cc6964192456dc243f27",
                    "PurchaseType": "PRODUCT",
                    "Code": "PAV2019",
                    "ExternalReference": "PAV2019QWE",
                    "Quantity": 1,
                    "SKU": null,
                    "CrossSell": null,
                    "Trial": null,
                    "AdditionalFields": null,
                    "Promotion": null,
                    "RecurringOptions": null,
                    "SubscriptionStartDate": null,
                    "SubscriptionCustomSettings": {
                        "CycleUnit": "MONTH",
                        "CycleLength": 1,
                        "CycleAmount": 50,
                        "CycleAmountType": "GROSS",
                        "ContractLength": 12,
                        "MerchantDealAutoRenewal": true,
                        "ClientDealAutoRenewal": true
                    }
                }
            ],
            "Promotions": [],
            "AdditionalFields": null,
            "CustomParameters": null,
            "Currency": "usd",
            "NetPrice": 47.06,
            "GrossPrice": 50,
            "NetDiscountedPrice": 47.06,
            "GrossDiscountedPrice": 50,
            "Discount": 0,
            "VAT": 2.94,
            "AffiliateCommission": 0
        }
    }
]

Error handling

Whenever there is a validation error, this will trigger an error response is returned, like below:

{
    "error_code": "INVALID_EES_TOKEN",
    "message": "The token is not valid. In order to proceed with the place order a valid token is required"
}

In this case, the deal order is not created, and you must correct the request parameters, as indicated, and retry the API call.

Most of the validation errors are common with the ones listed for the getDealInfo method (see the Errors handling).

Whenever there is a payment level error encountered, the amendment order is still created, and the payment processing error will be returned in the DealOrder.Errors element, in the usual format used by the placeOrder response as well, for example: 

[
    {
        "SubscriptionReference": "GUC9PFSIH8",
        ……
        "DealOrder": {
            "RefNo": "11662596",
            ……
            "Errors": {
                  "ORDER_PAYMENT_METHOD_CARD_PROCESS_ERROR": "Couldn't complete the payment validation process: Error processing the credit card transaction. Please contact the issuer bank for more details, or enter another card."
            }
        }
    }
]

You can check the list of possible order-level errors on this page

Rate this article:

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