Build the Callout Service
By the end of this lesson, you'll be able to:
- Build the payment gateway callout matching the contract from Lesson 1
- Return a typed result distinguishing success, decline, and error
- Keep the service itself unaware of Queueable or trigger concerns
Prerequisites: "Design the Payment Flow"
A typed result matching the three outcomes
public class PaymentResult {
public Boolean success;
public Boolean declined;
public String gatewayTransactionId;
public String message;
}
Three fields directly mirroring Lesson 1's three outcomes — success and declined together let a caller distinguish all three cases (success=true; success=false, declined=true; success=false, declined=false for an error), without needing a separate enum or extra parsing logic.
The callout itself
public class PaymentGatewayService {
public PaymentResult charge(Decimal amount, String paymentToken) {
HttpRequest request = new HttpRequest();
request.setEndpoint('callout:Payment_Gateway/charge');
request.setMethod('POST');
request.setBody(JSON.serialize(new Map<String, Object>{
'amount' => amount,
'token' => paymentToken
}));
HttpResponse response = new Http().send(request);
Map<String, Object> parsed = (Map<String, Object>) JSON.deserializeUntyped(response.getBody());
PaymentResult result = new PaymentResult();
if (response.getStatusCode() == 200) {
result.success = true;
result.gatewayTransactionId = (String) parsed.get('transactionId');
} else if (response.getStatusCode() == 402) { // "Payment Required" — the gateway's decline status
result.success = false;
result.declined = true;
result.message = (String) parsed.get('reason');
} else {
result.success = false;
result.declined = false;
result.message = 'Gateway error: ' + response.getStatusCode();
}
return result;
}
}
Notice paymentToken, not a raw card number — Lesson 4 covers exactly why. The three-way branch here is a direct implementation of Lesson 1's success/decline/error distinction, using the gateway's actual status codes to tell them apart.
Exercise
As a comment, explain why the service checks response.getStatusCode() == 402 specifically for a decline, rather than treating any non-200 as a decline.
Show hint
Think about what a 500 status would mean instead.
Build the Callout Service Quiz
My Notes
Log in to keep private notes on this lesson.
Questions about this lesson
No questions yet — be the first to ask.
Log in to ask a question about this lesson.
Summary
This lesson builds PaymentGatewayService — a plain, synchronous-looking callout service, deliberately unaware that it will only ever be called from inside an async context.