I am using pre-approvals and delayed chained payment from adaptive payment api.
My test business account from which api is used is also the primary receiver account.
I get a paykey generated after using the preapproval to initiate the delayed payment. The money is received accurately in the primary receiver. My application now has a scenario where the money has to be refunded from primary receiver back to the purchaser. When tyring to execute this refund with the paykey and specifying the receiver and also settings the primary receiver flag, I receive an error NO_API_ACCESS_TO_RECEIVER.
This is blocking my app release and is a serious trouble. Could you please unblock me at earliest.
This is my code:
RefundRequest refundRequest = new RefundRequest();
refundRequest.setPayKey(payKey);
refundRequest.setCurrencyCode(KeyConstants.CURRENCY_USD_CODE);
refundRequest.setRequestEnvelope(ClientInfoUtil.getMyAppRequestEnvelope());
ReceiverList receiverList = new ReceiverList();
Receiver receiver = new Receiver();
receiver.setEmail(businessAccountPaypalEmail);
receiver.setPrimary(true);
double truncatedAmount = NumberUtil.getDoubleTruncate(amount, KeyConstants.TWO_DECIMAL_FORMAT);
BigDecimal trunBigDecimal = new BigDecimal(truncatedAmount);
receiver.setAmount(trunBigDecimal.setScale(2, RoundingMode.HALF_UP));
receiverList.getReceiver().add(receiver);
refundRequest.setReceiverList(receiverList);
try {
AdaptivePayments adaptivePayments = new AdaptivePayments();
RefundResponse refundResponse = adaptivePayments.refund(refundRequest);
ResponseEnvelope responseEnvelope = refundResponse.getResponseEnvelope();
AckCode ackCode = responseEnvelope.getAck();
if(ackCode == AckCode.SUCCESS || ackCode == AckCode.SUCCESS_WITH_WARNING){
Logger.getLogger(PayPalSessionBean.class.getName()).log(Level.INFO, "Refund success for the pay key {0} and messsage {1}",
new Object[]{payKey});
System.out.println("Ack code is " + ackCode);
RefundInfoList refundInfoList = refundResponse.getRefundInfoList();
List<RefundInfo> refundInfos = refundInfoList.getRefundInfo();
for (Iterator iterator = refundInfos.iterator(); iterator
.hasNext();) {
RefundInfo refundInfo = (RefundInfo) iterator.next();
System.out.println(refundInfo.getReceiver().getEmail() + "\t" + refundInfo.getRefundTransactionStatus() + "\t" +
refundInfo.getRefundGrossAmount() + '\t' + refundInfo.getRefundStatus() + '\t');
ErrorList errorList = refundInfo.getErrorList();
List<ErrorData> errs = errorList.getError();
for (Iterator iterator2 = errs.iterator(); iterator2
.hasNext();) {
ErrorData errorData = (ErrorData) iterator2.next();
System.out.println(errorData.getMessage());
}
}
return true;
}
In the above code snippet the ACk code returned is success, but when I print the refund status of the RefundInfo object, it says NO_API_ACCESS_TO_RECEIVER.
I have already given the permission to the api caller from the paypal panel of the primary account.
Is there something that is missing from my side? Please help me out!
If your just refunding from the Primary (yourself) back to the sender and you want to do a full refund, then you shouldn't need to specify any receivers. Otherwise I would need some type of PayKey or Correlation ID to look up the request on my side.
Got the answer myself. Sharing with you all
It was reading the paypal SDK client property file from Wrong location.
To avoid such kind of problems we should set the properties in the constructor of AdaptivePayments.
Below is the code for more illustration:
There is a session bean PropertyBean which has function getPayPalProperties() which reads all paypal properties from a property file.
Properties properties = propertyBeanLocal.getPayPalProperties();
AdaptivePayments adaptivePayments = new AdaptivePayments(properties);
And Instead of doing this
refundRequest.setRequestEnvelope(ClientInfoUtil.getMyAppRequestEnvelope());
do this.
RequestEnvelope requestEnvelope = new RequestEnvelope();
requestEnvelope.setErrorLanguage("en_us");
refundRequest.setRequestEnvelope(requestEnvelope);
Related
I am creating an app that works like an authenticator for the website logins, I have setup a server of https://www.strongkey.com/ and here is the samples I am following https://github.com/StrongKey/fido2/tree/master/sampleapps/java/sacl/mobile/android.
But I am not aware how to achieve this facility, What my application is doing is
Hitting the pre register api and getting the challenge to register
sample response
{"Response":{"rp":{"name":"FIDOServer","id":"fidoidqa.com"},"user":{"name":"devendra","id":"s5wXaholuoVwk86KQ0d_hmIxOkQPNS-bBBes8X4Cex8","displayName":"devendraLiapC"},"challenge":"COJ03Ch_6KDjlvnZ1jg_Qw","pubKeyCredParams":[{"type":"public-key","alg":-7},{"type":"public-key","alg":-35},{"type":"public-key","alg":-36},{"type":"public-key","alg":-8},{"type":"public-key","alg":-47},{"type":"public-key","alg":-257},{"type":"public-key","alg":-258},{"type":"public-key","alg":-259},{"type":"public-key","alg":-37},{"type":"public-key","alg":-38},{"type":"public-key","alg":-38}],"excludeCredentials":[{"type":"public-key","id":"NEVDOUQzNkMzMDBEM0U3MS1FNDczNTQ3QUVDRDQ1ODDRELTk1MEJFOTM2NTI5MEIxNjctMTIxNkNFQjY1ODIzQTI5OQ","alg":-7},{"type":"public-key","id":"MUUzMDY0RkNGQUZEOTM5Ni1FMzlFOUM2MkUwOTQE4NzcwLTA0NzUyMEFBREM0ODUwM0UtMEU4ODdFOEFCRjFCMDE3QQ","alg":-7},{"type":"public-key","id":"hhkXnYmUiu_bzLy5HPHJvZs6TQA-302jRdeLHBgpL40","alg":-257}],"attestation":"direct"}}
Then with this response, I am creating the preregisterchallenge,
var preregisterChallenge = PreregisterChallenge() val authenticatorSelectionCriteria = AuthenticatorSelectionCriteria() authenticatorSelectionCriteria.authenticatorAttachment = "Android" authenticatorSelectionCriteria.isRequireResidentKey = true authenticatorSelectionCriteria.userVerification = "required" val authSelectionJson = Gson().toJson(authenticatorSelectionCriteria) val myCustomArray: JsonArray = Gson().toJsonTree(userData.Response?.pubKeyCredParams).asJsonArray preregisterChallenge.apply { id = 100 uid = 1001 did = 1003 rpid = userData.Response?.rp?.id userid = "1001" username = "devendra" displayName = "devendra" challenge = userData.Response?.challenge authenticatorSelectionJSONObject = JSONObject(authSelectionJson) authenticatorSelection = authSelectionJson publicKeyCredentialParams = myCustomArray.toString() credParamsJSONArray = JSONArray(myCustomArray.toString()) }
And then doing like this
val publicKeyCredential = AuthenticatorMakeCredential.execute( ContextWrapper(context), preregisterChallenge, "fidoidqa.com" ) as PublicKeyCredential
I am getting the publickKeyCredential without any error
Now I want to attest this key with biometric humen presence with this public key, for example now user will touch the biometric to verify this public key and then I will call the register api.
How can I attest the public key credential with the biometric fingerprint and want a signed public key credential for future verification.
Hope this is well explained, Please help me in understanding the flow or process.
Thanks in advance
I'm a beginner of android programming. I had started a test project which is about using an android app to access web service and run function there. I am using ksoap2 to call the web services.
When I want to login to a database through phone and the web service return a session ID to me. But after that, When I want to run other function in service, and I pass it in session ID, it tell me that there is a null object reference. I tried use the session ID again to get back the login details but it shows that the session doesn't point to any session. This is the method which allow me to connect with web services. While for android, I just simply call using ksoap2.
<WebMethod(True)> _
Public Function CompanyConnectionString() As String
Dim lErrCode, lRetCode As Long
Dim sErrMsg As String = ""
Dim sSessionID As String = ""
Dim oCompany As SAPbobsCOM.Company
oCompany = New SAPbobsCOM.Company
// User and other details to connect
oCompany.Server = "xx.x.x.xx" //ip address
oCompany.DbServerType = SAPbobsCOM.BoDataServerTypes.dst_MSSQL2012
oCompany.DbUserName = "dbUser"
oCompany.DbPassword = "dbPassword"
oCompany.CompanyDB = "CompanyDB"
oCompany.UserName = "User"
oCompany.Password = "Password"
oCompany.LicenseServer = "xx.x.x.xx:xxxxx" // ip
lRetCode = oCompany.Connect
If lRetCode <> 0 Then
oCompany.GetLastError(lErrCode, sErrMsg)
sSessionID = lErrCode & "-" & sErrMsg
Else
sSessionID = Session.SessionID.ToString
Session.Add(sSessionID, oCompany)
''
Cookies.SetCookies(oCompany, "SID")
End If
Return sSessionID
End Function
I found that it might lose the session ID and I can't get back the login details for other functions later. So is that any idea for that? How I gonna do? without this I can't proceed further in my program.
Thank in advance..
Well, the problem had just solved. Me and my friend found out that that is because the sessionID is forgotten due to the max-age=0;. So we add that to our sessionID and it ran.
if (headerKey != null) {
if (headerKey.equals("Set-Cookie")) {
cookieBuilder.append(headerValue + "max-age=86400;");
}
} //headervalue is the sessionID
This will allow the session to stay active for 86400 seconds = 1 day.
So the sessionID can be use for running other function on web service
I am creating new user on ejabberd server.The user gets created.
In the code below user 918 got created but no attribute were saved.
ejabberd server has access rule is : [register, [{allow,all}]]
However, the attributes that i pass along with createAccount(), do not get saved on the ejabberd server.
libraries used - asmack-android-8-4.0.7, dnsjava-2.1.7.
XMPP server - ejabberd 2.1.11
Code is
ConnectionConfiguration config = new ConnectionConfiguration("myserver.co");
config.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
conn1 = new XMPPTCPConnection(config);
conn1.connect();
AccountManager accMan = AccountManager.getInstance(conn1);
Map<String, String> attributes = new HashMap<String, String>();
attributes.put("phone", "237");
attributes.put("misc", "123");
accMan.createAccount("918", "hellopass", attributes);
conn1.login("918", "hellopass");
accMan = AccountManager.getInstance(conn1);
Log.d(TAG, "acc IMEI " + accMan.getAccountAttribute("misc")); // null returned here
Log.d(TAG, "acc phone " + accMan.getAccountAttribute("phone")); // null returned here
The last 2 lines of code posted above, return null value.
I do not know what am i missing to correctly create account with attributes too getting saved.
thanks
Vilpesh.
Attributes are not stored on the account but on the Vcard. When you register a user, you can only pass username and password.
For the user information, you should look into setting your Vcard.
I'm working on an Android app developed on Titanium SDK 3.2.0.GA and I'm using the In-App Billing module by Appcelerator.
My implementation of the module it's as follows (omitting functions which only purpose is to display log info):
var IdentifierProduct = '';
var InAppBilling = require('ti.inappbilling');
var publicKey = Alloy.Globals.Android.publicKey_1 + Alloy.Globals.Android.publicKey_2 + Alloy.Globals.Android.publicKey_3 + Alloy.Globals.Android.publicKey_4;
InAppBilling.setPublicKey(publicKey);
function initializeBilling()
{
var synchronousResponse = InAppBilling.checkBillingSupported();
displaySynchronousResponseCodes(synchronousResponse);
}
function requestPurchase(identifier, item_type)
{
// Check if billing for current product type is supported before sending purchase request
var checkBillingResponse = InAppBilling.checkBillingSupported(item_type);
if (checkBillingResponse.responseCode == InAppBilling.RESULT_OK)
{
Ti.API.info('Current product type supported, continuing with request');
var tmpArgs = {
productId: identifier,
productType: item_type,
developerPayload: 'devPayload'
};
Ti.API.info('args for product request\n' + JSON.stringify(tmpArgs));
var synchronousResponse = InAppBilling.requestPurchase({
// productId: 'android.test.purchased',
// productId: 'android.test.canceled',
// productId: 'android.test.refunded',
// productId: 'android.test.item_unavailable',
productId: identifier,
productType: item_type,
developerPayload: 'devPayload'
});
displaySynchronousResponseCodes(synchronousResponse);
}
else
{
Ti.API.info('Current product type not supported, aborting request');
displaySynchronousResponseCodes(checkBillingResponse);
}
}
function ON_BIND_EVENT(e)
{
if (e.result == InAppBilling.SUCCESS) {
NotifyMe('Billing Service Bound');
enableInAppPurchases(true);
//Call
} else {
NotifyMe('Billing Service Bind Failed');
enableInAppPurchases(false);
}
}
InAppBilling.addEventListener(InAppBilling.ON_BIND_EVENT, ON_BIND_EVENT);
function ON_CONNECT_EVENT(e)
{
NotifyMe('CONNECT CALLED');
if(Ti.App.Properties.getBool('transactionsRestores') === null)
{
Ti.API.info('fresh install, lets restore the transactions');
try
{
InAppBilling.restoreTransactions();
}
catch(err)
{
Ti.API.info('Error');
Ti.API.info(JSON.stringify(err));
}
}
}
InAppBilling.addEventListener(InAppBilling.ON_CONNECT_EVENT, ON_CONNECT_EVENT);
function RESPONSE_EVENT(e)
{
// Events with (e.sync == true) are deprecated and will be removed. Use the event object that the methods return.
if(!e.sync){
NotifyMe('RESPONSE CALLED ' + e.requestId + ' ' + e.responseCode);
Ti.API.info('RESPONSE CALLED \n' + 'Request Id:\n' + e.requestId + ' ' + '\nResponse Code:' + ResponseString(e.responseCode));
if(e.responseCode === InAppBilling.RESULT_ERROR)
{
// Error in request
Ti.API.info('Response event error');
Ti.API.info(JSON.stringify(e));
}
else if(e.responseCode === InAppBilling.RESULT_ITEM_UNAVAILABLE)
{
// Item unavailable in request
Ti.API.info('Response event item unavailable');
Ti.API.info(JSON.stringify(e));
}
}
}
InAppBilling.addEventListener(InAppBilling.RESPONSE_EVENT, RESPONSE_EVENT);
function PURCHASE_STATE_CHANGED_EVENT(e)
{
Ti.API.info('PURCHASE_STATE_CHANGED_EVENT Parameters:\n' + JSON.stringify(e) );
NotifyMe('PURCHASE STATE CHANGED CALLED ' + e.signedData + ' ' + e.signature+'\n'+ 'SECURITY RESULT ' + e.result);
Ti.API.info('PURCHASE STATE CHANGED CALLED');
Ti.API.info('Signature Verification Result:\n' + VerificationString(e.result));
Ti.API.info('Signed Data:\n' + e.signedData);
if (e.signedData != null) {
var response = JSON.parse(e.signedData);
/*
* We are not guaranteed to have any orders returned so
* we need to make sure that this one exists before using it.
*
* If there is no notificationId then there is no need to confirmNotifications().
* This happens when restoreTransactions() triggers a PURCHASE_STATE_CHANGED_EVENT.
*/
for(var i = 0; i < response.orders.length; i++)
{
if(typeof response.orders[i] !== 'undefined')
{
setPurchaseFlag(response.orders[i].productId);
}
if (response.orders[i] && response.orders[i].notificationId)
{
Ti.API.info('confirming notification for order ' + JSON.stringify(response.orders[i]));
var synchronousResponse = InAppBilling.confirmNotifications({
notificationIds: [response.orders[i].notificationId]
});
displaySynchronousResponseCodes(synchronousResponse);
}
}
}
}
InAppBilling.addEventListener(InAppBilling.PURCHASE_STATE_CHANGED_EVENT, PURCHASE_STATE_CHANGED_EVENT);
function NOTIFY_EVENT(e)
{
Ti.API.info('NOTIFY CALLED \n' + 'Notify Id:\n' + e.notifyId);
var synchronousResponse = InAppBilling.getPurchaseInformation({
notificationIds: [e.notifyId]
});
displaySynchronousResponseCodes(synchronousResponse);
}
InAppBilling.addEventListener(InAppBilling.NOTIFY_EVENT, NOTIFY_EVENT);
InAppBilling.startBillingService();
The following is a list of the steps I've reviewed to look for errors:
I've checked that my package name is the same as the one in my application draft in Play Store
I checked that my license key is correct
all of my In-App products are in active state
the request sent to the Play Store are with product ids that correspond to my In-App products.
My device account is in registered as a test account so it should let me make a purchase.
I added the In-App Products around two weeks ago and every time I try to request a purchase, all of them are return a not found response, Play Store couldn't take this long to activate the, right?
And yet, I get as a response "the item you are attempting to purchase could not be found".
The response code I get is 2, which I thought it meant RESULT_SERVICE_UNAVAILABLE, but the dialog that appears clearly says the item was not found, am I interpreting the response code wrongly? Or should I look into why the service is unavailable?
I followed the guide to test In-App purchases and I'm getting this error with no clear cause.
EDIT
I've been searching around and found a few questions (here and here) were developers get RESULT_SERVICE_UNAVAILABLE when making too many restoreTransactions() calls. I checked my code and saw that, indeed, I was making a restoreTransactions() call every time I launched the app.
Now I have added a validation on the ON_CONNECT_EVENT to make sure if there were transactions to restore at all, in case it doesn't then I set a flag that prevents the app from making a restoreTransactions() call the next it launches.
The problem, though, still remains, can I contact Google in some way to ask for my In-App services to be enabled again? How long do I have to wait? The users on those questions mention it could take up to 3 weeks, can we accelerate this process?
Unfortunately without In-App Purchases we cannot release our app.
Try publishing your app in alpha or beta. They have changed the way of doing tests and now this is required.
Cheers
I'm a newbie myself, but the methods, properties and events you are using do not appear in the current documentation -- perhaps your code expects an earlier version of InAppBilling.
I state that I am a complete beginner to LDAP.
I have to let a user change its own password through an Android device. User has NOT administrative privileges.
Using the UnboudId LDAP SDK for Java I'm able to bind to server and get the user entry using this code:
final SocketFactory _socket_factory;
final SSLUtil _ssl_util = new SSLUtil(new TrustAllTrustManager());
try {
_socket_factory = _ssl_util.createSSLSocketFactory();
}
catch (Exception e) {
Log.e(LOG_TAG, "*** Unable to initialize ssl", e);
}
LDAPConnectionOptions _ldap_connection_options = new LDAPConnectionOptions();
_ldap_connection_options.setAutoReconnect(true);
_ldap_connection_options.setConnectTimeoutMillis(30000);
_ldap_connection_options.setFollowReferrals(false);
_ldap_connection_options.setMaxMessageSize(1024*1024);
LDAPConnection _ldap_connection = new LDAPConnection(_socket_factory, _ldap_connection_options, [host ip], 636, [username], [password]);
Filter _filter = Filter.create("(userPrincipalName=" + [username] + ")");
SearchRequest _search_request = new SearchRequest([base DN], SearchScope.SUB, _filter);
_search_request.setSizeLimit(1000);
_search_request.setTimeLimitSeconds(30);
SearchResult _search_result = _connection.search(_search_request);
This works and I get 1 entry and all the relative attributes. Now my task is to change the password [password] with a new [new password].
My attempts:
PasswordModifyExtendedRequest _password_modify_request = new PasswordModifyExtendedRequest([found entry DN], [password], [new password]);
PasswordModifyExtendedResult _password_modify_result = (PasswordModifyExtendedResult)_ldap_connection.processExtendedOperation(_password_modify_request);
This doesn't work due to LDAPException
LDAPException(resultCode=2 (protocol error), errorMessage='0000203D: LdapErr: DSID-0C090C7D, comment: Unknown extended request OID, data 0, vece��', diagnosticMessage='0000203D: LdapErr: DSID-0C090C7D, comment: Unknown extended request OID, data 0, vece��')
Then I've tryed
final Modification _replace_modification = new Modification(ModificationType.REPLACE, "unicodePwd", _get_quoted_string_bytes([new password]));
LDAPResult _result = _connection.modify([found entry DN], _replace_modification);
This doesn't work due to LDAPException
LDAPException(resultCode=50 (insufficient access rights), errorMessage='00000005: SecErr: DSID-031A0F44, problem 4003 (INSUFF_ACCESS_RIGHTS), data 0)
Finally I've tryed
final Modification _delete_old_modification = new Modification(ModificationType.DELETE, "unicodePwd", _get_quoted_string_bytes([password]));
final Modification _add_new_modification = new Modification(ModificationType.ADD, "unicodePwd", _get_quoted_string_bytes([new password]));
final ArrayList<Modification> _modifications = new ArrayList<Modification>();
_modifications.add(_delete_old_modification);
_modifications.add(_add_new_modification);
LDAPResult _result = _connection.modify([found entry DN], _modifications);
This doesn't work due to LDAPException
LDAPException(resultCode=19 (constraint violation), errorMessage='00000005: AtrErr: DSID-03190F00, #1:0: 00000005: DSID-03190F00, problem 1005 (CONSTRAINT_ATT_TYPE), data 0, Att 9005a (unicodePwd)��', diagnosticMessage='00000005: AtrErr: DSID-03190F00, #1: 0: 00000005: DSID-03190F00, problem 1005 (CONSTRAINT_ATT_TYPE), data 0, Att 9005a (unicodePwd) ��')
And now i have no more ideas... Any help will be appreciated, thanks in advance
final Modification _delete_old_modification = new Modification(ModificationType.DELETE, "unicodePwd", ('"' + oldPassword + '"').getBytes("UTF-16LE"));
final Modification _add_new_modification = new Modification(ModificationType.ADD, "unicodePwd", ('"' + newPassword + '"').getBytes("UTF-16LE"));
Did the trick.
Finally, I was able to resolve CONSTRAINT_ATT_TYPE issue in password change. I had set minimum password age as 4 days, so AD wasn’t allowing me to update the password. AD throws generic error CONSTRAINT_ATT_TYPE for all such violations. After setting minimum password age as 0 (None), everything works fine. AD password history also gets updated.
Refer:
http://www.javaxt.com/Tutorials/Windows/How_to_Authenticate_Users_with_Active_Directory
"Minimum password age" was the source of my problem CONSTRAINT_ATT_TYPE