Marketplaces / TikTok Marketplace Integration / TikTok - Order management - OLD / TikTok - Cancel Order (Pre-shipment seller cancell

TikTok - Cancel Order (Pre-shipment seller cancellation) - OLD

Summary of changes:

Date Version Changes
27/06/2022 1.1 Some more info added re validation.
28/06/2022 1.2 changed the validation description (UI validation removed due to discussion)
15/08/2022 1.3 Changed requirements for displaying the reverse reasons
19/08/2022 1.4 Abstraction referred & add details re order statuses;
22/08/2022 1.5 Details re validations added;
Еrror message has been edited;

The purpose of this page is to give good understanding of the flow, where seller can cancel the order before the order is shipped.

The flow is quite straight forward - First we need to get the cancellation reasons from TikTok in order to use them when cancelling an order. This can be done via “Get Reverse Reason List“. Also, we need to display these reasons into the refund UI and to use them when cancelling an order. To cancel an order we should specify the order (using the unique order identifier - order_id and to specify the reason for cancelling it.

  • Get Reverse Reason List

First we need to make a call “Get Reverse Reason List“ and to get all the available reasons for TikTok. We need them because to cancel an order we should mandatory push the order ID & cancel reason key. We are able to cancel the whole order ( we are pushing the order_id).

We need to display the reverse_reason_key in refund UI when doing a refund for TikTok Order. This was agreed because we are allowed to set same reverse reason to different oorder statuses. In order to avoid misunderstanding and a repeatable information into the UI, we will display the reverse_reason_keys (instead of reverse reasons). Via this way we will send to TikTok what is is the reason key, the exact reason key will be displayed into the UI too & will be stored into the DB.

API Call: GET /api/reverse/reverse_reason/list

API Docs: https://developers.tiktok-shops.com/documents/document/237500

Example Response with reasons of cancellation:

{
    "code": 0,
    "message": "Success",
    "request_id": "202205191302120101920531420832D662",
    "data": {
        "reverse_reason_list": [
            {
                "available_order_status_list": [
                    200
                ],
                "reverse_reason": "Out of stock",
                "reverse_reason_key": "seller_cancel_reason_out_of_stock_uk"
            },
            {
                "available_order_status_list": [
                    200
                ],
                "reverse_reason": "Pricing error",
                "reverse_reason_key": "seller_cancel_reason_wrong_price_uk"
            },
            {
                "reverse_reason": "Buyer return reason is not valid",
                "reverse_reason_key": "reverse_reject_request_reason_1_uk"
            },
            {
                "reverse_reason": "Change of mind returns are not applicable",
                "reverse_reason_key": "reverse_reject_request_reason_2_uk"
            },
            {
                "reverse_reason": "Not eligible for return (e.g. used or broken)",
                "reverse_reason_key": "reverse_reject_request_reason_3_uk"
            },
            {
                "reverse_reason": "Product delivery is on schedule",
                "reverse_reason_key": "reverse_reject_request_reason_4_uk"
            },
            {
                "reverse_reason": "You have reached an agreement with the buyer",
                "reverse_reason_key": "reverse_reject_request_reason_5_uk"
            },
            {
                "reverse_reason": "Wrong/The product returned is not the product that was sent",
                "reverse_reason_key": "reverse_reject_return_parcel_reason_1_uk"
            },
            {
                "reverse_reason": "Not eligible for return (e.g. used or broken)",
                "reverse_reason_key": "reverse_reject_return_parcel_reason_2_uk"
            },
            {
                "reverse_reason": "Missing products and/or product parts",
                "reverse_reason_key": "reverse_reject_return_parcel_reason_3_uk"
            },
            {
                "reverse_reason": "I haven't received the package",
                "reverse_reason_key": "reverse_reject_return_parcel_reason_4_uk"
            },
            {
                "reverse_reason": "Package is damaged",
                "reverse_reason_key": "reverse_reject_return_parcel_reason_5_uk"
            },
            {
                "reverse_reason": "Invalid reason for cancellation",
                "reverse_reason_key": "order_manage_list_action_respond_popup_reject_reason_invalid_cancellation_reason_uk"
            },
            {
                "reverse_reason": "Product delivery is on schedule",
                "reverse_reason_key": "order_manage_list_action_respond_popup_reject_reason_delivered_uk"
            },
            {
                "reverse_reason": "Reached an agreement with the buyer",
                "reverse_reason_key": "order_manage_list_action_respond_popup_reject_reason_buyer_agree_uk"
            },
            {
                "available_order_status_list": [
                    0
                ],
                "reverse_reason": "Out of stock",
                "reverse_reason_key": "seller_cancel_unpaid_reason_out_of_stock_uk"
            },
            {
                "available_order_status_list": [
                    0
                ],
                "reverse_reason": "Pricing error",
                "reverse_reason_key": "seller_cancel_unpaid_reason_wrong_price_uk"
            },
            {
                "available_order_status_list": [
                    0
                ],
                "reverse_reason": "Buyer did not pay on time",
                "reverse_reason_key": "seller_cancel_unpaid_reason_buyer_hasnt_paid_within_time_allowed_uk"
            },
            {
                "available_order_status_list": [
                    0
                ],
                "reverse_reason": "Buyer requested cancellation",
                "reverse_reason_key": "seller_cancel_unpaid_reason_buyer_requested_cancellation_uk"
            },
            {
                "available_order_status_list": [
                    200
                ],
                "reverse_reason": "Buyer requested cancellation",
                "reverse_reason_key": "seller_cancel_paid_reason_buyer_requested_cancellation_uk"
            },
            {
                "available_order_status_list": [
                    200
                ],
                "reverse_reason": "Unable to deliver to buyer address",
                "reverse_reason_key": "seller_cancel_paid_reason_address_not_deliver_uk"
            }
        ]
    }
}

If reason is not specified we will be treating “seller_cancel_reason_out_of_stock_uk“ as default reason.

Once we store the reasons in Hemi, to proceed with cancellation, we should use the following API call:

  • Cancel Order

API Call: Post /api/reverse/order/cancel

API Docs: https://developers.tiktok-shops.com/documents/document/23750

  • Important: We are able to only cancel the whole order, including shipping cost ( we are pushing the order_id!). If we have 2 items into order and we try to cancel only one item, there should be error message (“Only full order refund is allowed.“), which will indicate we cannot cancel partially the order before the shipment i.e. only full refunds before the shipment are allowed, not partial. In other words, if we try to cancel order, the following condition should be covered:

Order Total Amount = Refund Amount

As per discussion we cannot handle such validation in the UI at this stage, so the validation will be handled only in the cron.

Example request:

{
  "cancel_reason_key": "",
  "order_id": ""
}

Mapping:

Integration Field Integration Notes Integration required Hemi Mapping Hemi Notes
cancel_reason_key Y Order Payment Details > Reason Based on the cancel_reason_key we need to display into the UI the “reverse_reason“
order_id Y Orders > Marketplace Order ID

Response example:

{
  "code": 0,
  "data": {
    "reverse_main_order_id": ""
  },
  "message": "Success",
  "request_id": "202203070749000101890810281E8C70B7"
}

Mapping:

Integration Field Integration Notes Integration required Hemi Mapping Hemi Notes
reverse_main_order_id Y Order Payment Details > Transaction ID with type “refund“

In order to send a refund to the marketplace we must have an Order Payment record where the Type = Refund and the Status = Pending and “Process by Marketplace” on “yes”. We are able to cancel orders which are on status “Ready for Shipping“ & “Incomplete“ (Refunds send general logic ).

Order Payment record will contain the general information like total of refund, transaction ID, date, reason, etc. and also we store Refund Row which is a connection to the actual items in the order. If we receive success, we should update the order status to “Cancelled“, refunded amounts in order and order items, internal payment statuses for order items and order item lines.

The refund rows contain the SKU, type of refund (item cost vs shipping cost) and is the direct referral to us knowing what is refunded on specific products and how much. We will have refund type = refund and status = completed

If we receive an error, we will set the status on error, and need to display the respective error in Error text field

Is this article helpful?
0 0 0