Handling Receipts

You can decide to either handle your own receipt screen implementation or allow the SDK to provide a base for you where you can implement specific functionality which then should be handled in your app.

This is done by providing a receipt delegate as part of the PaymentParameters and/or PaymentParameters which will cause the SDK to render a receipt screen that will be handled using the ReceiptDelegate.

If no delegate is provided, then the SDK will skip receipt screen and return after the completion screen. This will allow you to provide your own receipt screen implementation or do nothing.

Step 1: Implement the Receipt Delegate

You will need to implement the ReceiptDelegate to listen for callbacks from the receipt screen

import com.yoco.payment_ui_sdk.data.delegates.ReceiptDelegate
import com.yoco.payment_ui_sdk.data.enums.SupportedReceiptType
class SampleFragment: Fragment(), ReceiptDelegate {
// Provide a list of receipt types that you would like to show on the Receipt screen
override fun supportedReceiptTypes(): List<SupportedReceiptType> =
listOf(SupportedReceiptType.SMS, SupportedReceiptType.EMAIL, SupportedReceiptType.PRINT)
}

Step 2: Register the Delegate

You will need to pass the ReceiptDelegate to the SDK as part of the PaymentConfig

import com.yoco.payment_ui_sdk.YocoSDK
import com.yoco.payment_ui_sdk.data.config.PaymentConfig
import com.yoco.payment_ui_sdk.data.delegates.ReceiptDelegate
import com.yoco.payment_ui_sdk.data.params.PaymentParameters
import com.yoco.payment_ui_sdk.data.params.RefundParameters
class SampleFragment: Fragment(), ReceiptDelegate {
fun charge(amount: Long) {
val params = PaymentParameters(receiptDelegate = this)
// Access SDK
YocoSDK.charge(
context = context,
amountInCents = amount,
params = params
)
// OR
val params = RefundParameters(receiptDelegate = this)
// Access SDK
YocoSDK.refund(
context = context,
transactionId = <transactionId>,
params = params
)
}
}

Step 3: Implement Optional functions

To get notified of the receipt button presses from the receipt screen (Provided by the SDK), you will need to implement the callback functions that is linked to the ReceiptType that you have specified in the supportedReceiptTypes() function.

Supported Receipt Types

Receipt TypeValueCallback
SmsReceiptType.SMSsendSMSReceipt(number: String, paymentResult: PaymentResult, progress: UpdateReceiptProgress)
EmailReceiptType.EMAILsendEmailReceipt(address: String, paymentResult: PaymentResult, progress: UpdateReceiptProgress)
PrintReceiptType.PRINTprintReceipt(paymentResult: PaymentResult, progress: UpdateReceiptProgress)

It is up to you to decide how the receipt is handled. In each callback, it will provide you with a progress parameter - this allows you to control the receipt screen's selected button state.

It will also provide the current PaymentResult with the info related to the transaction result.

Receipt State

The receipt state can be changed multiple times, as long as you keep calling the state using the progress parameter. Each state represents a view change for the specific button [Incomplete (default), In progress, Error, Complete]

/**
* Glorified enum type class that manages the various receipt field (input or text) states that can be controlled by the 3rd party
*/
sealed class ReceiptState {
/**
* This is the default/empty state of the field
open class Incomplete : ReceiptState()
/**
* This is the completed state of the field (Green) - should be called after a successful execution - it will block further input from the field
*
* @property message - (Optional) complete message that will show in the completed state
*/
data class Complete(val message: String? = null) : ReceiptState()
/**
* This is the error state of the field (Red) - should be called when an error occurs eg. validation etc specifically to do with the field
*
* @property message - error message to display on field
*/
data class Error(val message: String) : ReceiptState()
/**
* This is the loading state of the field (Grey) - should be called when performing some action eg. printing the receipt etc
*
* @property message - (Optional) progress message that will show in the progress state
*/
data class InProgress(val message: String? = null) : ReceiptState()
}

Usage

import com.yoco.payment_ui_sdk.data.delegates.ReceiptDelegate
import com.yoco.payment_ui_sdk.data.delegates.UpdateReceiptProgress
import com.yoco.payment_ui_sdk.data.enums.ReceiptState
import com.yoco.payment_ui_sdk.data.enums.SupportedReceiptType
import com.yoco.payment_ui_sdk.data.params.PaymentParameters
class SampleFragment: Fragment(), ReceiptDelegate {
// Provide a list of receipt types that you would like to show on the Receipt screen
override fun supportedReceiptTypes(): List<ReceiptType> =
listOf(SupportedReceiptType.SMS, SupportedReceiptType.EMAIL, SupportedReceiptType.PRINT)
// Handle sending SMS receipt
override fun sendSMSReceipt(
phoneNumber: String,
paymentResult: PaymentResult,
progress: UpdateReceiptProgress
) {
if (validate(phoneNumber)) {
SendSMS({
progress(ReceiptState.Complete())
})
} else {
progress(ReceiptState.Error(message = "Phone number is invalid"))
}
}
// Handle sending Email receipt
override fun sendEmailReceipt(
address: String,
paymentResult: PaymentResult,
progress: UpdateReceiptProgress
) {
if (validate(address)) {
progress(ReceiptState.InProgress())
SendEmail({
progress(ReceiptState.Complete())
})
} else {
progress(ReceiptState.Error(message = "Email is invalid"))
}
}
// Handle printing a receipt
override fun printReceipt(paymentResult: PaymentResult, progress: UpdateReceiptProgress) {
progress(ReceiptState.InProgress(message = "Initialising..."))
PrintReceipt(object: PrintReceiptCallback {
override fun onComplete(v: View?) {
progress(ReceiptState.Complete(message = "Receipt Printed"))
}
override fun onPrintStarted(v: View?) {
progress(ReceiptState.InProgress(message = "Printing...."))
}
override fun onPrintError(v: View?) {
progress(ReceiptState.Error(message = "Printing error"))
}
})
}
}