question

gsm-tommy avatar image
gsm-tommy asked finacussolutions answered

Register screen not completing my order after the CFS is completed using a CF Tender

I'm stuck at completing the order on the Register screen after the Customer facing screen has completed the order using my custom customer facing tender.

Here is the flow I want;

1- Customer opens the register app and create an order

2- Customer choose my custom MODIFY ORDER BUTTON which opens my custom app to scan his/her giftcard and then click on my custom app "PAY" Button

3- Customer Facing Screen is pop-up and customer chooses my custom CUSTOMER FACING TENDER to make the payment

4- Customer click on my custom TENDER payment button on the Customer Facing Screen, the TIP Screen comes up which allows the customer to choose a TIP, after that my custom TENDER screen appears which allows the customer to click on the "APPROVE" button to finalize the payment

5- After the payment is completed on the Customer Facing Screen, customer will print a receipt on the Customer Facing Screen

6- The Register app should update the order and move to the checkout screen to print a receipt also on the Merchant Facing Screen


My current approach has make it to STEP 5 and this is my codes;


AndroidManifest.xml

<activity
            android:name=".CustomerFacingTenderActivity"
            android:exported="true"
            android:label="@string/tender_assign_gift_card"
            android:theme="@style/Theme.AppCompat.Light.NoActionBar">
            <meta-data
                android:name="clover.intent.meta.CUSTOMER_TENDER_IMAGE"
                android:resource="@mipmap/ic_launcher" />


            <intent-filter>
                <action android:name="clover.intent.action.CUSTOMER_TENDER" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
<activity
            android:name=".PayWithGiftCardActivity"
            android:exported="true"
            android:theme="@style/GiftCardDialogTheme">
            <intent-filter>
                <action android:name="clover.intent.action.MODIFY_ORDER" />


                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>


PayWithGiftCardActivity.kt

val saleRequest = com.clover.remote.client.messages.SaleRequest(
                doubleToLong(orderTotal),
                randomGenerator()
            )
            val cardEntryMethods =
                CloverConnector.CARD_ENTRY_METHOD_MAG_STRIPE or CloverConnector.CARD_ENTRY_METHOD_ICC_CONTACT or CloverConnector.CARD_ENTRY_METHOD_NFC_CONTACTLESS or CloverConnector.CARD_ENTRY_METHOD_MANUAL;
            saleRequest.cardEntryMethods = cardEntryMethods
            saleRequest.autoAcceptPaymentConfirmations = true
            saleRequest.autoAcceptSignature = true
            saleRequest.externalId = randomGenerator()
            saleRequest.tipMode = TipMode.ON_SCREEN_BEFORE_PAYMENT
            saleRequest.approveOfflinePaymentWithoutPrompt = true
            cloverConnector!!.sale(saleRequest)
override fun onSaleResponse(response: SaleResponse) {
                    var result = ""
                    var paymentObj: Payment? = null
                    if (response.isSuccess) {
                        result = "Payment was successful"
                        paymentObj = response.payment
                        runOnUiThread {
                            Toast.makeText(
                                application.applicationContext,
                                result,
                                Toast.LENGTH_LONG
                            ).show()
                        }
                        updateOrder(paymentObj.jsonObject, paymentObj.order.id)
                        
                    } else {
                        result =
                            "Payment was unsuccessful" + response.reason + ":" + response.message
                        runOnUiThread {
                            Toast.makeText(
                                application.applicationContext,
                                result,
                                Toast.LENGTH_LONG
                            ).show()
                        }
                    }
                    
                    cloverConnector!!.showWelcomeScreen()
                    finish()
                }


private fun updateOrder(
        extraPaymentObj: JSONObject,
        extraOrderId: String?
    ) {
val baseUrl = "https://sandbox.dev.clover.com"
        val url = "$baseUrl/v3/merchants/$merchantId/orders/$extraOrderId?forceRealTime=true"

        val jsonObject = JSONObject()

        val payObj = JSONArray()
        payObj.put(extraPaymentObj)

        val lineItems = JSONArray()
        for (lineItem in currentOrder!!.lineItems) {
            lineItems.put(lineItem.jsonObject)
        }

        jsonObject.put("payments", payObj)
        jsonObject.put("paymentState", PaymentState.PAID)
        jsonObject.put("payType", PayType.FULL)
        jsonObject.put("state", "LOCKED")
        jsonObject.put("note", "AGC ID: ${cardItems[0].number}")
        jsonObject.put("lineItems", lineItems)
        
        ApiRequest().updateOrder(
            url,
            cloverAccountToken!!,
            jsonObject,
            object : Callback {
                override fun onResponse(call: Call, response: Response) {
                    val body = response.body!!.string()

                    if (!response.isSuccessful) {
                        runOnUiThread {
                            Toast(applicationContext).showCustomToast(
                                body,
                                this@PayWithGiftCardActivity
                            )
                        }
                        return;
                    }

                    val jsonResponseBody = JSONObject(body)

                    if (jsonResponseBody.length() != 0) {
                        // Request successful
                    } else {
                        runOnUiThread {
                            // Request is not successful
                        }
                    }
                }

                override fun onFailure(call: Call, e: IOException) {
                    Log.e(TAG, "updateOrder()/onFailure: $e")
                    runOnUiThread {
                        Toast(applicationContext).showCustomToast(
                            "Error adding payment to order.",
                            this@PayWithGiftCardActivity
                        )
                    }
                }
            })
}


CustomerFacingTenderActivity.kt

class CustomerFacingTenderActivity : AppCompatActivity() {
    private lateinit var approveButton: Button
    private lateinit var declineButton: Button
    private lateinit var txtTotalAmount: TextView
    private lateinit var tipAmountText: TextView

    var amount: Long = 0
    var currency: Currency? = null
    var orderId: String? = null
    var tender: Tender? = null
    var tipAmount: Long = 0
    var merchantId: String? = null
    var note: String? = null
    var paymentId: String? = null
    var lineitemIds: IntArray? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_customer_facing_tender)

        setResult(RESULT_CANCELED)

        // Necessary for Customer Facing user experiences
        setSystemUiVisibility()

        if (intent.hasExtra(Intents.EXTRA_AMOUNT) && intent.hasExtra(Intents.EXTRA_ORDER_ID)
        ) {

            paymentId = intent.getStringExtra(Intents.EXTRA_PAYMENT_ID)
        amount = intent.getLongExtra(Intents.EXTRA_AMOUNT, 0)
        val currency = intent.getSerializableExtra(Intents.EXTRA_CURRENCY) as Currency?
        tipAmount = intent.getLongExtra(Intents.EXTRA_TIP_AMOUNT, 0)
        val orderId = intent.getStringExtra(Intents.EXTRA_ORDER_ID)
        tender = intent.getParcelableExtra(Intents.EXTRA_TENDER)

        lineitemIds = intent.getIntArrayExtra(Intents.EXTRA_LINE_ITEM_IDS)
            setupViews(amount, currency, orderId, merchantId, lineitemIds)

        }else{
            Toast.makeText(this, "No order found yet, redirecting to Main Gift Card App", Toast.LENGTH_SHORT).show()
        }
    }

    private fun setSystemUiVisibility() {
        if (!Platform2.supportsFeature(applicationContext, Platform2.Feature.CUSTOMER_MODE)) {
            window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                    or View.SYSTEM_UI_FLAG_LOW_PROFILE
                    or View.SYSTEM_UI_FLAG_FULLSCREEN
                    or 0x10000000)
        }
    }


    private fun setupViews(
        amount: Long,
        currency: Currency?,
        orderId: String?,
        merchantId: String?,
        lineitemIds: IntArray?
    ) {
        val amountText = findViewById<View>(R.id.txtAmount) as TextView
        amountText.text = getString(R.string.amount, longToAmountString(currency, amount))
        val orderIdText = findViewById<View>(R.id.txtOrderId) as TextView
        orderIdText.text = getString(R.string.order_id, orderId.toString())

        tipAmountText = findViewById<View>(R.id.txtTipAmount) as TextView
        tipAmountText.text = getString(R.string.tipAmount, longToAmountString(currency, tipAmount))

        txtTotalAmount = findViewById<View>(R.id.txtTotalAmount) as TextView
        txtTotalAmount.text = getString(R.string.total_amount, longToAmountString(currency, amount + tipAmount))

        approveButton = findViewById<View>(R.id.btnAccept) as Button
        approveButton.setOnClickListener{

            val data = Intent()
            data.putExtra(Intents.EXTRA_AMOUNT, amount)
            data.putExtra(Intents.EXTRA_CLIENT_ID, paymentId)
            data.putExtra(Intents.EXTRA_NOTE, "Payment Trx for AGC")
            data.putExtra(Intents.EXTRA_TIP_AMOUNT, tipAmount)
            data.putExtra(Intents.EXTRA_ORDER_ID, orderId)
            data.putExtra(Intents.EXTRA_LINE_ITEM_IDS, lineitemIds)
            data.putExtra(Intents.EXTRA_PAYMENT_ID, paymentId)
            setResult(RESULT_OK, data)
            finish()

        }
        declineButton = findViewById<View>(R.id.btnDecline) as Button
        declineButton.setOnClickListener{
            val data = Intent()
            data.putExtra(Intents.EXTRA_DECLINE_REASON, "You pressed the decline button")
            setResult(RESULT_CANCELED, data)
            finish()
        }
    }

}



I need to get this to production ASAP.

cc: @Jeffrey Blattman @bryan.vargas

Clover Android SDKREST APIPaymentsPaymentConnectorRemote Pay Android
10 |2000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

beckham86 avatar image
beckham86 answered

API Documentation: Check Clover's API documentation for the exact endpoints and request formats required to update orders. This will help ensure that your requests are correctly structured.

Error Handling: Implement robust error handling for each step to Among Us ensure that customers have a smooth experience, even if issues arise.

Testing: Thoroughly test the entire flow to ensure that all components work together seamlessly and that the Register app updates correctly after the payment is completed.

10 |2000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

finacussolutions avatar image
finacussolutions answered

To resolve the issue you're facing, ensure the following:

  • Verify that the order is properly linked between the customer-facing app and the register app after payment completion.
  • Double-check that the custom "TENDER" payment flow correctly triggers the register to update the order status post-payment, especially after the "APPROVE" button is clicked.
  • Ensure your custom app is sending a confirmation signal to the register app after the customer-facing screen completes the transaction.
  • Review integration settings between the register and customer-facing screens to ensure they synchronize properly for receipt printing and order completion.


10 |2000

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Welcome to the
Clover Developer Community