Skip to content

Customer Signup Flow for Payment Integrators

This document focuses on the endpoints that needs to be called in the Purchase Order Service (POS) and Payment Service ( PS) to sign up for a new service and make upfront payment. Calls to other related services are excluded.
The flow documented here is based on the current signup using the Client Interface and are subject to change.

Coverage and Product Selection

After navigating to the Coverage & Products, searching the address and selecting the relevant package, the Checkout page is loaded which requires calling a POS endpoint for the relevant product’s billing scheme, passing the previously selected productId.

GET https://stage.purchase-order-service.dev.aex.systems/configurations/billingScheme/Product/{productId}

file_type_swagger GetConfigurationTypeBillingScheme

User Details

The user then proceeds to enter their details, make their deferred payment selection, and click “Add Credit Card”. The user’s customer is created at this point with their login credentials as entered. This action is followed by a call to POS that includes the newly created customerId in the payload:

POST https://stage.purchase-order-service.dev.aex.systems/credit-card-details

file_type_swagger AddCreditCardDetails

Payload
1
2
3
{
  "customer_id": "061F4382-C3B2-4220-8585-D918B0FBECFD"
}

The above step creates a medium with medium_detail_id that is required for future actions.

Start Card Capturing

As some clients use Peach Payments as credit card provider, it is required to start the card tokenization process with the following purchase order service call:

POST https://stage.payment-service.dev.aex.systems/card-payments/checkout

file_type_swagger PrepareCheckout

Payload
1
2
3
4
5
{
  "amount": 1,
  "provider_id": "195CCAD5-02FC-4DC2-8589-7D85E44FFE30",
  "medium_detail_id": "aab5f0ea-6889-4e0c-acc6-62597e6253b2"
}

This information is required to generate the card capture form. Take care to include the previously obtained medium_detail_id in your ShopperRedirectUrl, so that it is available when Peach Payments redirects after form submission.

Tokenization

The following call to the POS updates the medium created earlier with the relevant token information, using the ResourcePath parameter that Peach Payments include in the redirect url.

PUT https://stage.purchase-order-service.dev.aex.systems/medium/customer/F208C1CE-ACD8-4D4D-9A95-17B8F3492D95/mediums/card

file_type_swagger Update Card Medium

Payload
1
2
3
4
5
{
  "provider_id": "195CCAD5-02FC-4DC2-8589-7D85E44FFE30",
  "medium_detail_id": "bf18a7d6-67f6-44ea-b3db-0e31450a172e",
  "resource_path": "/v1/checkouts/7C9A06D7BC7A2BEB0280B837D6F97EAF.uat01-vm-tx03/payment"
}
Example Response
{
  "descriptor": "NNN Checkout 9041.3499.0912",
  "recurring_type": "INITIAL",
  "card": {
    "bin": "424242",
    "bin_country": "GB",
    "last4_digits": "4242",
    "holder": "test1234",
    "expiry_month": "06",
    "expiry_year": "2026"
  },
  "customer": {
    "ip": "160.0.198.182",
    "ip_country": "ZA"
  },
  "custom_parameters": {
    "standing_instruction_api": "true",
    "ctpe_descriptor_template": "${INVOICE_ID} ${CHANNEL_NAME} ${SHORT_ID}",
    "stored_credential_type": "CIT",
    "standing_instruction": "UNSCHEDULED",
    "shopper_end_to_end_identity": "d3bb86590fdd9b7f9a3322cdca02f61c203c161755139ddc541733d3c6f90f85"
  },
  "risk": {
    "score": "0"
  },
  "standing_instruction": {
    "source": "CIT",
    "type": "UNSCHEDULED",
    "mode": "INITIAL",
    "initial_transaction_id": "{E5516170-7BE4-4B99-91A2-A38D7E3E4426}"
  },
  "result_details": {
    "connector_tx_i_d1": "{E5516170-7BE4-4B99-91A2-A38D7E3E4426}",
    "connector_tx_i_d2": "{ADE5D9F2-7CD0-431E-BA4E-2DA4EAC67D93}|9041.3499.0912",
    "connector_tx_i_d3": null,
    "action_code": null,
    "issuer_network_action_code": null,
    "scheme_transaction_id": null,
    "extended_description": null,
    "clearing_institute_name": null,
    "token_ch": null,
    "token_by": null,
    "status_details": null,
    "acquirer_response": "0",
    "draft_capture_flag": null
  },
  "three_d_secure": {
    "eci": "07",
    "verification_id": null,
    "xid": null,
    "pa_res": null
  },
  "is_medium_valid": null,
  "error_message": null,
  "result": {
    "code": "000.100.110",
    "description": "Request successfully processed in 'Merchant in Integrator Test Mode'"
  },
  "build_number": "3991bdf112fb62e208d5ec70cd98435b5afb1ed0@2023-11-22 00:52:28 +0000",
  "timestamp": "2023-11-22T08:21:53+00:00",
  "ndc": "7C9A06D7BC7A2BEB0280B837D6F97EAF.uat01-vm-tx03",
  "id": "8ac7a4a18bf3f213018bf61f13df1a98",
  "base_url": null,
  "registration_id": "8ac7a4a28bf3f48b018bf61f135f1686",
  "payment_type": "PA",
  "payment_brand": "VISA",
  "amount": "1.00",
  "currency": "ZAR",
  "merchant_transaction_id": "R4ULKKTAO76H5UTD"
}
Should the card fail to tokenize, the user must then retry and not allowed to continue order placement without a valid tokenized credit card.

Place Order

Once credit card tokenization is complete, the user selects their preferred debit day and continue with placing their order for service. The options of the available debit days to select from is found in the product’s billing scheme: recurrence_scheme.allowed_days.
Order placement actions the following chained calls:

  1. Full Service call to ISP Interface
  2. Details and actions call to POS
  3. Update debit day call to POS
  4. Update plan payment medium call to POS
  5. Details and actions call to POS
  6. Submit purchase for collection call to POS

Full Service Call to ISP Interface

This call creates the service with its serviceID, required for all subsequent actions.

POST https://stage.isp-interface.dev.aex.systems/services/full

file_type_swagger https://editor.swagger.io/?url=https://stage.fno.dev.aex.systems/swagger/schema.yaml

Payload
{
  "work_order": null,
  "premise": {
    "street_number": "151",
    "street_name": "Boeren Street",
    "suburb": "Vryheid",
    "city": "Vryheid",
    "province": "KwaZulu-Natal",
    "country_code": "ZA",
    "postal_code": "3100",
    "name": "WebSignUp_20231122082155986",
    "latitude": -27.7716006,
    "longitude": 30.7906964,
    "formatted_address": "151 Boeren St, Vryheid, 3100, South Africa",
    "external_reference": "Pending Approval"
  },
  "customer": {
    "id": "F208C1CE-ACD8-4D4D-9A95-17B8F3492D95",
    "first_name": "k",
    "last_name": "dp",
    "email": "konstandNet99@preprod1106.com",
    "mobile_number": "0000000000",
    "home_number": null,
    "business_name": null,
    "registration_number": null,
    "fno_opt_in": true,
    "isp_opt_in": true
  },
  "service": {
    "product_id": "042C2583-84A6-41BE-8EC4-808577263F66",
    "preorder": false
  },
  "force_index": true,
  "bypass_feasibility": true,
  "bypass_premise": true
}
Example Response
{
  "customer": {
    "id": "F208C1CE-ACD8-4D4D-9A95-17B8F3492D95"
  },
  "premise": {
    "id": "5DBCA817-74A9-4E18-BBDE-605E4592A188"
  },
  "service": {
    "id": "E14C231D-5899-44BE-B7A1-AA46893C8D83"
  },
  "payment_attribute": {
    "id": null
  }
}

Details and Actions Call to POS

This call gets the full details and available actions from POS. If POS is not yet aware of the newly created service (which it gets notified of via SQS messages), it will trigger a discovery event to get all relative information from FNO. After the debit day and payment medium calls are done, this call is repeated to get the correct upfront purchase under must_pay_info, to be submitted for collection.

GET https://stage.purchase-order-service.dev.aex.systems/services/E14C231D-5899-44BE-B7A1-AA46893C8D83/details-and-actions

file_type_swagger Get Service Details and Actions

Example Response
{
    "service_id": "E14C231D-5899-44BE-B7A1-AA46893C8D83",
    "service_status": "PendingIspApplication",
    "service_status_category": "PreActivationStatuses",
    "collector_id": "195ccad5-02fc-4dc2-8589-7d85e44ffe30",
    "service_type": "Recurring",
    "billing_status": "InArrears",
    "latest_period_end_date": null,
    "suspension_date": null,
    "collection_day": 15,
    "plan_id": "3e0ddf82-8912-459a-a6ec-f6640fdf8206",
    "mediums": [
        {
            "external_reference": "2903c73f-d075-4344-b034-888050375c1b",
            "customer_id": "2e15812f-34d7-4903-898e-ed3dcc6704a1",
            "medium_detail_id": "f3fe1a0a-c27b-4860-8159-6b94eb4c608d",
            "medium_type": "CreditCard",
            "medium_status": "Valid",
            "created_date": "2024-06-06T07:09:11.74847+00:00",
            "account_name": "test 4242",
            "account_number": "4242"
        },
        {
            "external_reference": "a8104184-86e0-4bb3-bf68-35197d916ed8",
            "customer_id": "2e15812f-34d7-4903-898e-ed3dcc6704a1",
            "medium_detail_id": "52db8e7c-bfbc-4e30-981b-c6477abdc59e",
            "medium_type": "PaymentLink",
            "medium_status": "Valid",
            "created_date": "2024-06-06T07:09:45.136321+00:00",
            "account_name": "konstandNet99@alpha.20240606.1",
            "account_number": ""
        },
        {
            "external_reference": "fa19f2f6-9737-4d0e-9c51-0234ae725940",
            "customer_id": "2e15812f-34d7-4903-898e-ed3dcc6704a1",
            "medium_detail_id": "58668902-5c08-45b0-b7ea-92fd760f1244",
            "medium_type": "OffSystem",
            "medium_status": "Valid",
            "created_date": "2024-06-06T07:09:45.204251+00:00",
            "account_name": "N/A",
            "account_number": null
        },
        {
            "external_reference": "Global PeachPayment provider selected opaque medium",
            "customer_id": null,
            "medium_detail_id": "aa8b416b-a7d9-4bc0-af81-041722e11ad4",
            "medium_type": "ProviderSelectedOpaque",
            "medium_status": "Valid",
            "created_date": "2023-10-12T04:36:37.252574+00:00",
            "account_name": "Add new payment method",
            "account_number": null
        }
    ],
    "must_pay_info": {
        "must_pay": true,
        "arrears_purchase": {
            "id": "62289f11-d7b4-4160-b51b-61c1a780be3b",
            "service_id": "7fe336c2-2dfd-4c3f-b9a4-14f76a828e53",
            "amount_excl": 329.70,
            "tax_amount": 49.20,
            "amount": 378.90,
            "medium_id": "f3fe1a0a-c27b-4860-8159-6b94eb4c608d",
            "purchase_date": "2024-06-06T07:09:45.250524+00:00",
            "purchase_status_id": 3,
            "payment_reference": null,
            "small_key": 1928142,
            "purchase_plan_id": null,
            "period_applied": false,
            "purchase_source_id": null,
            "purchase_creation_event_id": 1,
            "purchase_lines": [
                {
                    "id": "63eefe80-0ca9-431d-9105-65d56d1561c9",
                    "purchase_id": "62289f11-d7b4-4160-b51b-61c1a780be3b",
                    "original_purchase_line_id": null,
                    "purchase_line_type_id": 1,
                    "description": "On Order/Upfront Monthly",
                    "total_amount": 378.9000,
                    "amount_per_quantity": 10.9900,
                    "net_amount_excl": 329.70,
                    "tax_rate": 15.0,
                    "tax_amount": 49.20,
                    "quantity": 30,
                    "period_contribution_per_quantity": 1,
                    "product_price_id": "41d48ce6-753e-4678-96b2-7f2f08fee202"
                }
            ]
        }
    },
    "can_buy_info": null,
    "last_purchase_is_pending": false,
    "on_network_date": null
}

Update Debit day Call to POS

This call to POS sets the customer's debit day according to the option that was selected by the customer.

PUT https://stage.purchase-order-service.dev.aex.systems/services/E14C231D-5899-44BE-B7A1-AA46893C8D83/debit-day/15

file_type_swagger Set Debit Day

Example Response (failure)
1
2
3
4
5
6
7
{
  "type": "error:purchase-order",
  "title": "PurchaseOrder",
  "status": 500,
  "detail": "Payment day cannot be changed due to billing scheme payment day frequency cap being hit.",
  "instance": "/services/E14C231D-5899-44BE-B7A1-AA46893C8D83/debit-day/15"
}
Example Response (success)
1
2
3
4
5
6
7
{
    "new_payment_amount": null,
    "new_payment_date": null,
    "pro_rata_amount": null,
    "pro_rata_days": null,
    "result": "Payment day changed for service E14C231D-5899-44BE-B7A1-AA46893C8D83"
}

Update Plan Payment Medium Call to POS

This call to POS updates the plan with the medium detail id that was created and selected earlier. This medium will be used for every recurring debit run purchase.

PUT https://stage.purchase-order-service.dev.aex.systems/plan-medium-update/E14C231D-5899-44BE-B7A1-AA46893C8D83/f3fe1a0a-c27b-4860-8159-6b94eb4c608d

file_type_swagger Update Plan Payment Medium

Example Response (success)
1
2
3
{
    "result": "Plan with id 3e0ddf82-8912-459a-a6ec-f6640fdf8206 updated with medium detail id f3fe1a0a-c27b-4860-8159-6b94eb4c608d"
}

Submit Upfront Purchase For Collection Call to POS

After again calling 'Get Service Details and Actions', use the purchase contained in must_pay_info and submit it to POS for collection. NOTE: this is only executed if upfront payment via Credit Card was selected.

POST https://stage.purchase-order-service.dev.aex.systems/purchases/submit-for-collection

file_type_swagger Submit Purchase For Collection

Payload
1
2
3
4
5
6
7
{
  "service_id":"E14C231D-5899-44BE-B7A1-AA46893C8D83",
  "medium_id":"f3fe1a0a-c27b-4860-8159-6b94eb4c608d",
  "success_url":null,"failure_url":null,
  "process_immediate_purchase":true,
  "purchase_id":"62289f11-d7b4-4160-b51b-61c1a780be3b"
}
Example Response (failure)
1
2
3
4
5
6
7
{
  "type": "https://tools.ietf.org/html/rfc7235#section-3.1",
  "title": "Unauthorized",
  "status": 401,
  "detail": "Unauthorized",
  "instance": "/purchases/submit-for-collection"
}
Example Response (success)
1
2
3
{
  "payment_link_url":null
}

Success of this call should be followed by relevant success page, upload of RICA documents and a view of purchase history.

When the operator has payment links enabled as a payment option, the payment link is generated by the POS so that when this medium is selected for payment, the user is redirected to the payment page to complete their payment. This payment link medium is automatically generated for the customer after placing an order.

The POST call mentioned above (Submit Purchase For Collection) will contain a URL in the response that the user can be redirected to for payment:

Example Response
1
2
3
{
  "payment_link_url": "https://sandbox.payfast.co.za/eng/process/payment/123456ab-1234-ab12-907b-821e62f56789#cc"
}

Create a New Medium with Existing Medium Information

TO BE DEVELOPED

A new medium is created against an existing customer using existing payment information like a credit card token. Note that this is not part of the signup flow, but rather an alternative way to persist an existing token that was created outside the payment system against an existing user.

POST https://stage.purchase-order-service.dev.aex.systems/purchase-plan/customer/{customerId}/mediums

Payload
{
  "provider_id": "195CCAD5-02FC-4DC2-8589-7D85E44FFE30",
  "medium_type": "CreditCard",
  "details": {
    "credit_card_info": {
      "brand": "visa",
      "expiry_year": 2026,
      "expiry_month": 6,
      "last4_digits": "3674"
    },
    "provider_info": {
      "version": "1.0",
      "info_type": "PeachPayMinimal",
      "info": {
        "registration_id": "8ac7a4a28bf3f48b018bf61f135f1686"
      }
    }
  }
}

The Details.ProviderInfo.Info value contains dynamic information proprietary to the specific TPPP implementation. For this implementation, all that is required for Peach Payments are the RegistrationId, which is the token for the card.

Peach Payment Credit Card Tokenization

To tokenize a card through Peach Payments, their CopyAndPay API is used. Please see their online documentation for details https://peachpayments.docs.oppwa.com/tutorials/integration-guide/registrationtokens

When the operator has PayFast as a payment provider, the payment link is generated by the POS so that when this medium is selected for payment, the user is redirected to the PayFast payment page to complete their payment. This payment link medium is automatically generated for the customer after placing an order.

The following POST call is made to the POS to generate the payment link medium manually:

POST https://stage.purchase-order-service.dev.aex.systems/payment-link-medium-details

file_type_swagger Add PaymentLink MediumDetails

Payload
1
2
3
4
{
  "collector_id": "84AA6146-DCAB-4355-B6E9-54F7EFAC2BD3",
  "customer_id": "FFCD2B9E-A747-467E-90FD-ED5FAC4178D3"
}

The response will contain the MediumDetailId that is required to fulfill a purchase using it.

Example Response
{
  "external_reference": "99b3a9aa-4d5f-437a-95f4-372291db5e98",
  "customer_id": "d5dbfede-3529-46cb-a012-26380510feb9",
  "medium_detail_id": "0a768f17-b6a1-47c6-8b26-0eb9d35e30b0",
  "medium_type": "PaymentLink",
  "medium_status": "Valid",
  "created_date": "2024-09-17T12:32:47.608314+00:00",
  "account_name": "{user's email address}",
  "account_number": ""
}