Closed hamzabinamin closed 6 years ago
@hamzabinamin Let me investigate for 1. and 2. However, for these queries, I recommend to ask via our official support channel directly as we cannot reveal some account-specific information on public forums.
3) -> Yes paid=true
means the charge is complete.
4) -> Not with empty return_uri
but we have mechanism in the SDK to detect redirection to a specific URI and does the callback dance for you.
cc: @Namiii @nuxzero @pitiphong-p for 4 (how to) and 5 🙏
For 4. you should always handle these at the web server level anyway as it is possible for the end-user to modify the return-uri and trick the app into thinking that you are paid.
For 5. Android used setResult(int, intent)
to pass the result back to onActivityResult(int requestCode, int resultCode, Intent data)
. You can use CreditCardActivity.RESULT_CANCEL
or CreditCardActivity.RESULT_OK
to handle result back from startActivityForResult
like this.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CC:
if (resultCode == CreditCardActivity.RESULT_CANCEL) {
return;
}
Token token = data.getParcelableExtra(CreditCardActivity.EXTRA_TOKEN_OBJECT);
// process your token here.
default:
super.onActivityResult(requestCode, resultCode, data);
}
}
@hamzabinamin your account is 3ds-enabled already.
@nuxzero @chakrit How can I test the otp scenario on the test account? For test account, the authorization activity processes payment and displays the return URL, there's no way to determine if the user entered correct otp and paid the payment. Also will the live account work with testing cards mentioned on your website?
This is how I am calling the authorization acitivty
public static int AUTHORIZING_PAYMENT_REQUEST_CODE = 111;
// customer card already saved, so calling the charge API, the charge API returns the authorized URL
`CustomerCalls.chargeCustomer(PaymentFragment.this, customer.omiseID);`
if(success) {
String authorizedURL = charge.get("Authorized_URL").getAsString();
showAuthorizingPaymentForm(authorizedURL);
}
public void showAuthorizingPaymentForm(String authorizedURL) {
String[] array = {"https://www.mywebsite.com"};
Intent intent = new Intent(getContext(), AuthorizingPaymentActivity.class);
intent.putExtra(AuthorizingPaymentActivity.EXTRA_AUTHORIZED_URLSTRING, authorizedURL);
intent.putExtra(AuthorizingPaymentActivity.EXTRA_EXPECTED_RETURN_URLSTRING_PATTERNS, array);
startActivityForResult(intent, AUTHORIZING_PAYMENT_REQUEST_CODE);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
System.out.println("onActivityResult got called");
if (requestCode == AUTHORIZING_PAYMENT_REQUEST_CODE && CreditCardActivity.resultCode == RESULT_OK) {
String url = data.getStringExtra(AuthorizingPaymentActivity.EXTRA_RETURNED_URLSTRING);
System.out.println("Result OK, returning URL: " + url);
}
else {
System.out.println("Got in else, returning URL: " + resultCode);
}
}
In this case I always get result code as 0. Why is that?
Also I have noticed today that none of the testing card listed on (https://www.omise.co/api-testing) are working. On every card I am getting "Payment was rejected by the issuer or acquirer with no specific reason". All these cards were working fine before I submitted this ticket, is this because of 3DS?
@hamzabinamin
1) We don’t provide the real OTP scenario for test account however you can test the flow by setting the return_url
and go through authorized_url
comes with the charge data. Also, you can not use the card number on live mode too.
2) The code bug
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
System.out.println("onActivityResult got called");
if (requestCode == AUTHORIZING_PAYMENT_REQUEST_CODE && CreditCardActivity.resultCode == RESULT_OK) {
...
}
Follow your code, you should use resultCode
in onActivityResult()
not from CreditCardActivity.resultCode
. And make sure you use RESULT_OK
from android.app.Activity
.
The 0
code meant RESULT_CANCELED
please make sure have correct request.
3) On the payment rejected error, please make sure you test with the test account’s key.
Hope this should solve your problem.
@nuxzero
I was using the test card for successful charge. It's number is 4111-1111-1111-1111. I am also getting the transaction ID as null. All of these cards were working fine before 3ds got enabled.
Is it possible that I can use real cards on test account without having the charge deducting money from the card? That way I can test the otp scenario I believe.
Also I think I found out the problem, when authorization activity finishes processing the payment, it displays the URL given in return_url, but then I press the back button and I get the result code as 0.
Now the confusion is, when the return url is displayed, how do I determine if the otp was correct and payment as successful at that point? And then depending on the scenario return back to the app? Can you provide a code example to do that?
Please check the status property of the charge. If the charge needs to be authorized with OTP then the status will be other status than successful
which the charge may not have the transaction
yet.
No, the test account will be run in the contained environment which doesn’t connect to the bank. But you can test on the live account and refund after created charge.
That right, onActivityResult()
will return RESULT_CANCELED
when press back.
how do I determine if the OTP was correct and payment as successful at that point?
You need to have your backend to fetch the updated charge data from Omise and communicate back to your mobile client. The AuthorizingPaymentActivity
will detect if the flow direct to url same as you sent AuthorizingPaymentActivity.EXTRA_AUTHORIZED_URLSTRING
to AuthorizingPaymentActivity
. Then will auto direct back to the place that you call startActivityForResult()
with result RESUL_OK
and AuthorizingPaymentActivity.EXTRA_RETURNED_URLSTRING
. However by redirecting back to return URL doesn’t mean if the charge was succeeded or failed or anything other than the customer finished the authorization process. You still need to have you backend to fetch the updated status of charge and communicate back to your mobile client
For sample:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == MainActivity.AUTHORIZING_PAYMENT_REQUEST_CODE && resultCode == RESULT_OK) {
String url = data.getStringExtra(AuthorizingPaymentActivity.EXTRA_RETURNED_URLSTRING);
Toast.makeText(getApplicationContext(), url, Toast.LENGTH_LONG).show();
}
super.onActivityResult(requestCode, resultCode, data);
}```
@nuxzero Thanks for explaining the flow. I have one last confusion.
When the return URL is displayed, what trigger should be there that can close the authorization activity and send the result code of 1? Because after the payment gets processed, the authorization activity displays the return URL that I provided but it doesn't get closed by itself and if I press the back key it returns a result of 0.
@hamzabinamin the AuthorizingPaymentActivity
will return the result when its web view was redirected to a URL that matches the expected URL patterns argument. Please check your expected URL patterns argument if it’s the prefix of the returned URL
@pitiphong-p thank you for providing that information. I see, that EXPECTED_URL_PATTERNS takes an array of URL strings, what will be the use case in which we might need more than one return URL?
@hamzabinamin You can have only 1 return URL per charge but the reason that EXPECTED_URL_PATTERNS is an array is for the case that you have multiple variant of URL patterns
@pitiphong-p Do you have an example for this?
An example for which case?
@pitiphong-p An example for the scenario where we might have multiple variants of URL patterns?
We don’t have any concrete example here. This feature is provided in case where a business requirement need to have multiple return URLs patterns. For example a business may have many lines of products and would like to have multiple returned URLs patterns for each product lines
@pitiphong-p While I was able to solve my initial problem and now I do get the successful result in onAcitvityResult. But I am not been able to retrieve the charge ID after the authorization process. The way my code is structured, I somehow need a way to pass some data(charge id, customer id etc) to onAcitivtyResult so that I can perform a call to my backend. I tried doing the following but its returning null for charge id
Intent intent = new Intent(getContext(), AuthorizingPaymentActivity.class);
intent.putExtra(AuthorizingPaymentActivity.EXTRA_AUTHORIZED_URLSTRING, authorizedURL);
intent.putExtra(AuthorizingPaymentActivity.EXTRA_EXPECTED_RETURN_URLSTRING_PATTERNS, array);
intent.putExtra("Charge ID", "234");
startActivityForResult(intent, AUTHORIZING_PAYMENT_REQUEST_CODE);
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
System.out.println("onActivityResult got called");
Utilities.hideHUD(hud);
if (requestCode == AUTHORIZING_PAYMENT_REQUEST_CODE && resultCode == RESULT_OK) {
String url = data.getStringExtra(AuthorizingPaymentActivity.EXTRA_RETURNED_URLSTRING);
String chargeID = data.getExtras().getString("Charge ID"); // null
String chargeID2 = data.getStringExtra("Charge ID"); // null
}
...
}
If I can't send data through intent, is there any other way?
@hamzabinamin We can't provide more information from our Activity. However the practice that many merchants do is that the return URL contains some information related to the order/charge which you can parse the returned URL and asks for related information from your server based on the parameter in the returned URL
@pitiphong-p sending get parameters in the return URL is safe?
How to place the charge id as parameter in the return url? The following doesn't seem to work;
$charge = OmiseCharge::create(array(
'amount' => $amount,
'currency' => 'THB',
'customer' => $omiseid,
'card' => $cardid,
'return_uri' => 'http://www.buddiesmart.com'
));
$charge['return_uri'] = 'http://www.buddiesmart.com/chargeid=$charge['id']';
Any way I can access the charge id while the charge object is being created?
Something like the following:
$charge = OmiseCharge::create(array(
'amount' => $amount,
'currency' => 'THB',
'customer' => $omiseid,
'card' => $cardid,
'return_uri' => 'http://www.buddiesmart.com/chargeid=$charge['id']'
));
You shouldn't send the Omise charge id back with the returned URL. The data that we recommend to put in the returned URL is a piece of data that you can look up back to your order/data in your system that is associated with an Omise charge. For example your order id or a piece of an order that unique for that order and you can look up for an order with that data.
Hi there, I recently got my app approved from the omise review team and they suggested that I should add 3d secure as well. They mentioned that they have activated 3d secure on my account. I have a few questions:
@fred @sirn @chakrit @robinclart @SullysMustyRuby