Read the SRD: Renew CanalBox Internet Subscription. A CanalBox customer renews their internet package and pays on IremboGov; CanalBox renews the subscription and the application is approved automatically. No officer is involved.
You use the endpoints; you do not build them
The five CanalBox endpoints below already exist on staging, with mocks behind them and fixed test data. Your job is the service manager's: the right field, the right code, the right payload keys. Building an integration (endpoint, mapping, authentication, mock) is covered in Course 2: Integration Manager Certification.
From the SRD to the configuration
| SRD item | What it says | What you configure |
|---|---|---|
| Workflow | Apply → Pay → Integrate, in RWF. Payment valid 1 hour, SLA 5 minutes | APPLY (bill), PAY with a sync INTEGRATION push → APPROVED ("Subscription Renewed"), EXPIRE_PAYMENT, and a late PAY from PAYMENT_EXPIRED |
| Payment | Merchant GOR, account GOR-CG-RWF, service payment code RRA-31e2dcebcd (staging values) |
Pricing |
| Identify the customer | Radio: router serial number or phone number | Radio identifyBy (ROUTER / PHONE); the next fields depend on it. Both lookups also fill the hidden helper selectedRouter, which the package fetches read |
| Router serial | Fetch fills the customer names | Generic data fetch routerNumber → COURSE_CANALBOX_VERIFY_USER |
| Phone number | Fetch lists the customer's routers | Text field phoneNumber + paginated dropdown phoneRouter → COURSE_CANALBOX_ROUTERS_BY_PHONE |
| Renew previous package? | Yes: show the fetched previous package. No: dropdown of packages with prices | Radio renewPreviousPackage (YES / NO); No shows dropdown internetPackage → COURSE_CANALBOX_OFFERS |
| Duration | 1, 2, 3, 6 or 12 months; total from a preview-amount API | Dropdown subscriptionDuration; fetch COURSE_CANALBOX_AMOUNT_PREVIEW fills number field totalPrice; pricing Price From Attribute on totalPrice |
| Statuses | Payment Pending, Paid, Approved ("Subscription Renewed") | States and translations |
| Integrations | Section 2 of the SRD: four fetches on the form and one push on PAY, with their endpoint codes and payload keys | The course endpoints below. Production CanalBox calls back (async); the training mock cannot, so the SRD uses a sync push (lessons C3 and C3b) |
The CanalBox training endpoints: use these field keys exactly
| Endpoint code (staging) | Where | Send (payload keys) | Get back |
|---|---|---|---|
COURSE_CANALBOX_VERIFY_USER |
Generic data fetch on routerNumber |
routerNumber |
accountName, currentPackage, subscriptionStatus, endDate, currency |
COURSE_CANALBOX_ROUTERS_BY_PHONE |
Paginated dropdown phoneRouter (FIELD_LISTENER) |
phoneNumber |
routers[]: routerNumber (bindValue), label (bindLabel), accountName, currentPackage |
COURSE_CANALBOX_OFFERS |
Paginated dropdown internetPackage (FIELD_LISTENER) |
routerNumber, read from selectedRouter (payloadKeyMappings) |
offers[]: name (bindValue), label (bindLabel), pricePerMonth |
COURSE_CANALBOX_AMOUNT_PREVIEW |
Two hidden conditional fetches (FIELD_LISTENER), one per renewal choice: previewSamePackage and previewNewPackage |
routerNumber (from selectedRouter), renewPreviousPackage, subscriptionDuration, and internetPackage for a new package |
totalPrice, currency, months, newPackage |
COURSE_CANALBOX_RENEWAL_PUSH |
Workflow: INTEGRATION on PAY, async: false | The whole application; it reads applicationNumber, routerNumber or phoneRouter, renewPreviousPackage, internetPackage, subscriptionDuration, totalPrice |
Saved on the application: canalBoxTransactionId, subscriptionEndDate |
Test data (synthetic: these customers exist only in the mocks)
| Test value | Behaviour |
|---|---|
CBXK0001 |
Active, CanalBox 50 Mbps, Claudine Uwase. Renewing the same package costs 20,000 RWF per month |
CBXK0002 |
Expired, CanalBox 100 Mbps, same customer. Same package: 30,000 RWF per month |
CBXK0003 |
Being moved to a new address: the lookup, the price preview and the push answer 400 "This router is being moved…" |
CBXK9999 (any other) |
Not found: 400 with CanalBox's message |
0788100200 |
Phone with two routers: CBXK0001 and CBXK0002 |
0788100300 |
Phone whose only router is being moved: empty list |
| Packages | CanalBox 50 Mbps 20,000 · 100 Mbps 30,000 · 200 Mbps 45,000 RWF per month |
| Durations | 1, 2, 3, 6 or 12 months; any other value answers 400 |
Gotcha · the push reads your field keys
The push sends every form value under its field key, and the endpoint's mapping looks for the keys in the table above. A field called
ROUTER_SERIALinstead ofrouterNumbersends nothing: CanalBox answers "routerNumber, transactionNumber, prepaidPeriod (1, 2, 3, 6 or 12) and amount are required." and PAY fails. The Endpoint mapping panel of the INTEGRATION action warns you when a key is missing.
Gotcha · a listener needs a field that always exists
A FIELD_LISTENER fetch with several payload keys fires only when every source field it found has a value, and it does not notice a field that appears later. That is why the package fetches read the helper
selectedRouter(kept by hideField) instead ofrouterNumberorphoneRouter. Read section 3.3 of the SRD, then run its TC6 and TC7: switch the method and the renewal choice, and check the list and the total follow.
Tip · getting fetched data where you need it
The SRD lists only the fields the citizen sees. To make a fetch fill other fields you often need hidden helper fields the SRD does not mention, like
selectedRouter. That is normal practice. Four rules:
- A field must exist to receive data.
hideremoves the field from the form, so anything fetched into it is lost. Useprops.hideFieldfor fields a fetch fills (it only hides them on screen); keephidefor fields the citizen fills in.- Use full paths across blocks. If the target is in another block, write
section.block.fieldand setpopulateRelativeToRootForm: true.- A dropdown picks a value; it does not fill other fields. To fill fields from the chosen item, add a hidden fetch field that listens to the dropdown and calls the endpoint.
- Start a listener only when its inputs are ready. A hidden fetch that depends on an answer (for example "Renew? = Yes") should use the same
hiderule as the field it fills.Inside a block's own expressions,
modelmeans that block only. To read a sibling block, usefield?.parent?.model?.<block>?.<field>.Test every path, not just the first one: each "identify by" option and each Yes/No branch, checking every field that should fill.
Your turn · deliverable
Your trainer reviews: the Jira ticket with open questions answered, the change request link, one application number that reached Approved (with its
canalBoxTransactionId), the error the applicant saw on the router lookup withCBXK0003(it happens on the form, before any application exists), and a screenshot of the Kibana push lines of your approved application.
← C3b · Reading an async workflow · D1 · Submit to QA and the review loop →