Checkout with Subscription

Checkout is ideal when you have the traditional shopping cart checkout, where you want to have Upodi return the prices continuously as the cart changes and in the end gets committed

When dealing with a subscription purchase in a Webshop or other type of application, you need to be able to present the final price, the VAT, the available add-on purchases among other things in a shopping cart. This is also in order to be able to tokenize the payment method with the correct amount up-front and do the first purchase, allowing quick rejection in cases where the purchase is being rejected by the payment service provider.

This guide assumes you have already created and configured your Product Plan and you know how to create a Customer.

👍

Idempotency key

Checkout relies on you using the idempotency-key header, which in this case really helps with never sending a sign-up request twice. See Idempotency.

Step 1: Send the Checkout request

Find the Checkout Endpoint documentation here.

curl --location --request PUT 'https://api-front.upodi.io/Checkout' \
--header 'X-version: {version}' \
--header 'Authorization: Bearer {apiKey}' \
--header 'Idempontecy-key: {uniqueKey}' \
--header 'Content-Type: application/json' \
--data-raw '{
  "CustomerID" : "guid, required",
  "Currency": "string, required",
  "Subscription" : { 
     "ProductPlanID" : "guid, required",
     "SubscriptionNumber": "string?",
     "StartDate": "datetime?",
     "DiscountCode": "string?"
  }
}'

CustomerID: The customer object you want to subscribe. Important in order to know Taxation (VAT).
Currency: The chosen currency for the purchase in format "EUR".
Subscription: If the checkout includes a subscription purchase include the subscription object.
ProductPlanID: The product plan the customer is about to subscribe to.
SubscriptionNumber: Optional leave out to auto-assign.
StartDate: Optional only include this if start date is not now.
DiscountCode: Optional apply a discount code.

The response you get is the full checkout object:

{
  "CustomerID" : "guid",
  "Currency": "EUR",
  "FirstChargeOption" : "integer",
  "Subscription": { 
     "ProductPlanID": "guid",
     "StartDate": "2022-02-22 11:47:53.543",
     "SendActivationEmail": false,
     "Charges": [
     	{
        "ProductPlanChargeID" : "guid",
        "Quantity" : "1",
        "UnitPrice" : "50",
        "Skip" : "false",
        "ChargeDate" : "2022-02-22 11:47:53.543"
     	},
     	{
        "ProductPlanChargeID" : "guid",
        "Quantity" : "0",
        "UnitPrice" : "100",
        "Skip" : false,
        "ChargeDate" : "2022-02-22 11:47:53.543"
     	}
  	],
  },
  "Payment": {
    "Source": "subscriptionToken",
    "Gateway": "string",
    "MakeDefault": "bool?"
  }
  "Result": {
    "SummaryInvoice": {
         "InvoiceDate: "2022-02-22 11:47:53.543",
         .....
		}
  }
}

The structure of the checkout object

Apart from the parameters you already specified yourself there's going to be a few new ones here.

Charges: This contains all the item-purchases initially with all the quantities and unitprices from your configuration. Overwrite quantity and/or unitprice to change the checkout result. Skip is a boolean to control the first billing cycle of each charge as chosen in FirstCharge:
Payment: Optional The possibility to fill in the customers' tokenized payment method. Not needed before the final commit made in step 4.
SummaryInvoice: This is a complete invoice example if the checkout was to be committed. The invoice object is read only meaning all changes to the first purchase would happen through manipulating the Charges and hereby getting a new Summary Invoice result.

Step 2: Optional change the quantities and prices

You can change the checkout basket of the customer anytime you want and nothing is committed in these PUT requests.

curl --location --request PUT 'https://api-front.upodi.io/Checkout' \
--header 'X-version: {version}' \
--header 'Authorization: Bearer {apiKey}' \
--header 'Idempontecy-key: {uniqueKey}' \
--header 'Content-Type: application/json' \
--data-raw '{
    "CustomerID" : "guid",
    "Currency": "EUR",
    "Subscription": { 
    	 "ProductPlanID": "guid",
       "SubscriptionNumber": "SUB-20000053",
       "StartDate": "2022-02-22 11:47:53.543",
       "SendActivationEmail": false,
       "Charges": [
        {
            "ProductPlanChargeID" : "guid",
            "Quantity" : "1",
            "UnitPrice" : "50",
            "Skip" : "false",
            "ChargeDate" : "2022-02-22 11:47:53.543"
        },
        {
            "ProductPlanChargeID" : "guid",
            "Quantity" : "1",
            "UnitPrice" : "100",
            "Skip" : "false",
            "ChargeDate" : "2022-02-22 11:47:53.543"
        }
    	]
  	},
    
}'

The response would be a new result with an updated Invoice according to the new Items changes.

Step 3: Input the customer's payment method

Depending on the customer's chosen payment method you might have to prepare the payment method as a token fx. if the payment method is a credit card. Read more on how to do that in our Credit Cards section and for your specific provider or a Wallet type payment method.

In this example we continue using Nets Easy:

curl --location -g --request POST 'https://api.dibspayment.eu/v1/payments' \
--header 'Authorization: {NetsEasySecretKey}' \
--header 'Content-Type: application/json' \
--header 'Idempontecy-key: {uniqueKey}' \
--header 'Accept: application/json' \
--data-raw '{
    "order": {
        "items": [
            {
                "reference": "{invoiceline.sku}",
                "name": "{invoiceline.title}",
                "quantity": 1.0,
                "unit": "pc",
                "unitPrice": 50,
                "taxRate": 2500,
                "taxAmount": 12.5,
                "grossTotalAmount": 62.5,
                "netTotalAmount": 50
            },
            {
                "reference": "{invoiceline.sku}",
                "name": "{invoiceline.title}",
                "quantity": 1.0,
                "unit": "pc",
                "unitPrice": 100,
                "taxRate": 2500,
                "taxAmount": 25,
                "grossTotalAmount": 125,
                "netTotalAmount": 100
            }
        ],
        "amount": 162.5,
        "currency": "EUR"
    },
    "checkout": {
        "termsUrl": "http://ourterms.com",
        "merchantHandlesConsumerData": true,
        "charge": false,
        "returnUrl": "https://example.com/confirmation"
    },
    "subscription": {
        "endDate": "2060-07-18T00:00:00+00:00",
        "interval": 0
    }
}'

Where the payment provider supports it do avoid actually charging the payment. Here chosen by Charge set to false. Refer to your payment service provider to know how and if this is possible for your provider. The Items section of the payment call here contains all the invoice lines from the SummaryInvoice result from earlier.

This enables Upodi to be able to go in and find the authorization and then capture it in the next step.

Step 4: Post the checkout to Upodi with payment object

curl --location --request POST 'https://api-front.upodi.io/Checkout' \
--header 'X-version: {version}' \
--header 'Authorization: Bearer {apiKey}' \
--header 'Idempontecy-key: {uniqueKey}' \
--header 'Content-Type: application/json' \
--data-raw '{
    "CustomerID" : "guid",
    "Currency": "EUR",
    "PaymentFailureStrategy": 2,
    "FirstChargeOption": 0,
    "Payment": {
        "Source": "{\"SubscriptionId\":\"{SubscriptionId}\",\"PaymentId\":\"{PaymentId}\"}",
        "Gateway": "dibs_easy",
        "MakeDefault": "true"
    },
    "Subscription": { 
     "ProductPlanID": "guid",
     "StartDate": "2022-02-22 11:47:53.543",
     "SendActivationEmail": false,
     "Charges": [
     	{
        "ProductPlanChargeID" : "guid",
        "Quantity" : "1",
        "UnitPrice" : "50",
        "TotalVat": "12.5",
        "Skip" : "false",
        "StartDate" : "2022-02-22 11:47:53.543"
     	},
     	{
        "ProductPlanChargeID" : "guid",
        "Quantity" : "1",
        "UnitPrice" : "100",
        "TotalVat": "25",
        "Skip" : false,
        "StartDate" : "2022-02-22 11:47:53.543"
     	}
  	]
  }
}'

Source is filled in with the SubscriptionId from Nets Easy in this case and the PaymentId. For other providers refer to the individual docs to find our what goes in source.

Other optional POST parameters

When you do the final commit there's a few options available, which affects the way the checkout is handled.

PaymentFailureStrategy: Optional Send 2 if you don't want failed or abandoned payments to be created in Upodi. Will instead return an error directly. Default is 1 which would create the signup regardles of a failed payment.

FirstChargeOption: Optional Option to skip the first payment attempt in a subscription or invoice purchase in the checkout if you fx. perform the payment outside of Upodi. Just send 0 to actually attempt the payment in Upodi with the payment, which is also the default if not provided.

SendActivationEmail: Optional if configured in your email template set you can choose to send an email upon activation.

If the payment was successful you receive a 200 response along with an entire JSON body containing both the values you input but also the now committed Invoice object and the newly created PaymentMethod object. In case of payment failure it depends on your choice of PaymentFailureStrategy.