question

Bryanne Vega avatar image
Bryanne Vega asked Raymond Lee Deactivated commented

Payment & Order Association

Greetings,

I've been instructed to modify my app & I've tried several options without success.

I'm trying right now to start an activity for result (manual sale) with the amount already filled. On success I get the payment from the Intent's Extras. After doing:

Payment payment = data.getParcelableExtra(Intents.EXTRA_PAYMENT);

order.setPayType(PayType.SPLIT_CUSTOM);

order.setPayments(Collections.singletonList(payment));

orderConnector.updateOrder(order);
I receive the following message:

status code: 400 cannot update one or more of these fields: Order{json='{"payments":{"elements":[{"result":"SUCCESS","createdTime":000000,"taxRates":{"elements":[{"id":"UNIQUEID","taxableAmount":200,"taxAmount":0,"rate":0,"isVat":false,"name":"NO_TAX_APPLIED"}]},"offline":false,"id":"UNIQUEID","amount":200,"cashTendered":500,"tipAmount":null,"taxAmount":0,"lineItemPayments":null,"order":{"id":"UNIQUEID"},"tender":{"id":"UNIQUEID","enabled":true,"instructions":null,"visible":true,"labelKey":"com.clover.tender.cash","label":"Cash","opensCashDrawer":true,"editable":false},"employee":{"id":"UNIQUEID"},"externalPaymentId":null,"cashbackAmount":null}]},"payType":"SPLIT_CUSTOM"}', bundle=null, changeLog=null}

  1. Is it because the manual sale activity already associates that payment with a new order?
  2. Is there a work around or suggestions to this implementation?
  3. Can I start the register activity to go straight to payments with a pre-filled amount for this order?
  4. Is there a way to de-associate or simply associate the payment to a specific order id?
Thank you!





OrdersClover Android SDK
1 comment
10 |2000

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

Bryanne Vega avatar image Bryanne Vega commented ·

Extra details:

  • Secure Payment Doesn't Work, It won't allow cash or other tenders
  • Manual sale (ACTION_MANUAL_PAY) won't work, I figure the payment being made is automatically associated with a new order for it to be attached.
    • Also you can't add the order ID as a param (unless it's not documented).
  • V1 Active Pay order only allows an order ID to be passed

The goal: App needs the order to meet a minimum amount paid of the order so it can proceed it's logic & I can't get it approved unless I make it do so without having the merchant going back and forth between tenders & payments.

0 Likes 0 ·
Raymond Lee avatar image
Raymond Lee Deactivated answered Raymond Lee Deactivated commented
If you are trying to create multiple partial payments, each one possibly having a different tender type, you will need to do so through our REST API, as we currently do not support creating Payment objects through Android SDK.

Here is how to do so:

We will be using the /orders/{orderId}/Payments endpoint, to create a payment with a specified tender type.

1. Get the tender id of the type of tender you wish to use (for example cash):
TenderConnector mTenderConnector = new TenderConnector(getApplicationContext(), mAccount, null);
String tenderId;
for (com.clover.sdk.v1.tender.Tender t: mTenderConnector.getTenders()) {
    if (t.getLabelKey().equals("com.clover.tender.cash")) {
        tenderId = t.getId();
    }
}

2. Send a POST request to /orders/{orderId}/Payments with the tenderId, amount, and cashTendered (for cash tenders).

private RequestQueue mRequestQueue;

// In onCreate()
Cache cache = new DiskBasedCache(getCacheDir(), 1024 * 1024); // 1MB cap
Network network = new BasicNetwork(new HurlStack());
mRequestQueue = new RequestQueue(cache, network);
mRequestQueue.start();
...
CloverAuth.AuthResult authResult = CloverAuth.authenticate(getApplicationContext(), mAccount);
final String authToken = authResult.authToken;
String baseUrl = authResult.authData.getString(CloverAccount.KEY_BASE_URL);
String merchantId = authResult.merchantId;
String orderId = "3Y49B3EQVT4G6"; // Just for example; get your orderId from OrderConnector.

if (authToken != null && baseUrl != null) {
    String url = baseUrl + "/v3/merchants/" + merchantId + "/orders/" + orderId + "/payments";

    JSONObject params = new JSONObject();
    JSONObject tenderObj = new JSONObject();
    tenderObj.put("id", tenderId);
    params.put("tender", tenderObj);
    params.put("amount", 100); // $1 payment
    params.put("cashTendered", 500); // $5 received


    JsonObjectRequest jsObjRequest = new JsonObjectRequest(
            Request.Method.POST, url, params, new Response.Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject response) {
            try {
                // You can get any info you want from the response using
                // response.getJSONObject() or response.getJSONArray()
            }

            catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            error.printStackTrace();
        }
    }) {
        @Override
        public Map<String, String> getHeaders() throws AuthFailureError {
            HashMap<String, String> headers = new HashMap<String, String>();
            headers.put("Authorization", "Bearer " + authToken);

            return headers;
        }
    };

    mRequestQueue.add(jsObjRequest);

Hope that helps,

Raymond
18 comments
10 |2000

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

Bryanne Vega avatar image Bryanne Vega commented ·

Alright, let's see if this sinks in,

I have an order which total is $10.00
The minimum amount that the order must have paid partially in order to continue my logic is 50%.

I can direct the merchant to a manual sale activity (which supports providing a pre-filled amount of 500 (long)), if the payment is complete & successful, then I should call this end-point & POST a new Payment Object with whatever Tender (cash, credit, etc) they used and the amount, this will reflect the order now has $5.00 paid out of the order's total ($10.00)

  1. Once this is done I can refresh the Order and it should have a Payment of $5.00 so I can continue my logic?
  2. Wouldn't this affect in any way the merchant's reporting (example: 2 payments of $5.00 which would throw off their reporting?

Thanks for the support!

0 Likes 0 ·
Raymond Lee avatar image Raymond Lee Bryanne Vega commented ·

1. My above answer is for creating a new payment with any amount you specify, and attaching it to the orderId you specify. Manual Sale activity will not work, as that will create a new Order and attach the payment with the amount specified to it.

If your app requires the order to have 50% already paid, you can handle the payments in your app to reach the 50% using the SecurePay app for partial credit card payments (since you can specify orderId & amount), and the orders/{orderId}/payments endpoint to create other types of payments (you can specify orderId & amount here too).

After each payment, you can iterate through the order's list of payments, add up the amounts, and see if it is above or equal to 50%. Then continue with your app's logic.

2. As stated, Manual Sale activity will not work due to it creating a new order, and you are correct in that this will throw off the reporting, as an extra $5.00 will be reported.

0 Likes 0 ·
Bryanne Vega avatar image Bryanne Vega Raymond Lee commented ·

I can definitely use the SecurePay for credit card/debit payments & I can do cash within my own app and the issue would be resolved?

0 Likes 0 ·
Show more comments
Raymond Lee avatar image
Raymond Lee Deactivated answered Bryanne Vega commented
Hi @Bryanne Vega,

1. That is correct, Manual Sale is for creating a one time transaction that will create a new order.

2/3. Yes, if you are taking other forms of payment (Cash, custom tender, etc.), I recommend you use ACTION_CLOVER_PAY instead with your orderID passed in as an extra, which will launch the Payments App with your Order amount & lineItems pre-filled. See the JavaDoc link for ACTION_CLOVER_PAY to see the other extras you can pass in.

Here is an example of how to use ACTION_CLOVER_PAY:

// Intent to Start Clover Pay App.
Intent intent = new Intent(Intents.ACTION_CLOVER_PAY);
intent.putExtra(Intents.EXTRA_ORDER_ID, orderID);
startActivity(intent);

// Can also use startActivityForResult() if you want to know the result,
// need to write an onActivityResult():
// Request Code is to know where result came from in onActivityResult() 
// private static final int CLOVER_PAY_REQUEST_CODE = 1;
// startActivityForResult(intent, CLOVER_PAY_REQUEST_CODE);

4. Assuming the above solution works for you, I don't think you will need to change the payment association. Let me know if this is not the case.

Hope that helps,

Raymond
5 comments
10 |2000

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

Bryanne Vega avatar image Bryanne Vega commented ·

It's almost the right answer, except I can't pre-fill the partial amount to be paid for example:

if the order total is $10.00, the 10% is $1.00 I need to open the Pay Activity with the Order's ID & the 100 (long) amount so all the customer has to do is hit "Pay with cash" or swipe the card.

0 Likes 0 ·
Bryanne Vega avatar image Bryanne Vega commented ·

At best I could indicate the customer that there's a minimum due and they need to split custom amount pay the $1.00 in order to continue the app's logic. But it'll be the same as setResult Cancelled & finish, which brings them to the Clover Pay Screen which is a no-go :/

0 Likes 0 ·
Bryanne Vega avatar image Bryanne Vega commented ·

A probable solution would be to:

  • Be able to accept any tenders & associate the payment with my order
  • Be able to start Clover PAY with Order ID, Amount & Pay Type specified so it'll jump straight onto tender selection
0 Likes 0 ·
Raymond Lee avatar image Raymond Lee Bryanne Vega commented ·

Ah ok, I was not aware the payment was going to be a part of a set of partial payments, in that case the best solution would be through the REST API, as we currently do not support the ability to create Payment objects through Android SDK. I will follow up with an answer on how to do so.

0 Likes 0 ·
Bryanne Vega avatar image Bryanne Vega Raymond Lee commented ·

Awesome!

Remember,

Once the merchant hits our tender and our app opens, the order must already have met the amount of % paid towards the order's final value in order for our logic to proceed. Since this won't always be the case, we're letting the merchant know a minimum is due & they must do that before continuing. Once that threshold is met (by making a payment to that specific order) the user should be returned as a result (for an activity) and we'll check the order and continue if the conditions are met.

I'm not allowed to publish until this happens, I can't tell the user they need to make a partial payment for the due amount then hit "Next payment" and select our Tender because this doesn't make the app intuitive. Makes sense since the logic is a bit weird but it's the only way I've found so far to accomplish our app's goal within the SDK.

Thanks for your support!

0 Likes 0 ·

Welcome to the
Clover Developer Community