I have a confusion with Braintree. When a customer orders certain item on site, he makes a charge on BT with his credit card and I need to check this payment via Java client. I found the following code:
Transaction transaction = gateway.transaction().find("the_transaction_id");
But I need to search by orderId, a special ID that my system issues on every order event. How to do that in BT with Java API?
Although you may be able to persist the orderId on the Braintree side, I don't readily see a way to perform a lookup on it directly.
Here's how we handle it:
Persist your orderId with the transaction ID that you get back from Braintree. When you need to do your check, look up your table using the orderId, find the transactionId, and call the same find() method to find the payment.
I'd imagine you'd do something like:
//some paymentService
public Result<Transaction> sale(BigDecimal amount,
String nonce,
String firstName,
String lastName,
String postalCode) {
TransactionRequest request = new TransactionRequest()
.customer()
.firstName(firstName)
.lastName(lastName)
.done()
.billingAddress()
.firstName(firstName)
.lastName(lastName)
.postalCode(postalCode)
.done()
.type(Type.SALE)
.amount(amount)
.paymentMethodNonce(nonce)
.options()
.submitForSettlement(true)
.done();
return gateway.transaction().sale(request);
}
//and then...
Result<Transaction> result = paymentService.sale(amount, nonce, firstName, lastName, postalCode);
if (result.isSuccess()) {
Transaction transaction = result.getTarget();
String transactionId = transaction.getId(); //persist this ID and your orderId together in your DB
...
}
//when you need to find payment details, it'd be like:
Order order = someService.find(orderId);
PaymentHistory paymentHistory = order.getPaymentHistory();
String transactionId = paymentHistory.getTransactionId();
Transaction transaction = gateway.transaction().find(transactionId);
Related
I want to mask out some field when logging.
is there any good way to mask out?
after message is served to client.
I'm trying to mask out some field before logging
how do you mask out field?
--served to client
message {
id : "user",
phoneNumber : "12341234"
}
--logged response
message {
id : "user",
phoneNumber : "12******"
}
I don't think there is a way to alter the data like you mentioned, however there is a way to hide field that you don't want to print in the log (I assume its for security reasons). The way yo do that is with FieldMask.
So for the sake of the example I took the liberty of adding another field to the schema I assume you have:
message User {
string id = 1;
string name = 2;
string phone_number = 3;
}
So now let's say that I don't want to show the phone number of my users, I can use a FieldMask to keep only id and name. So first we build a FieldMask (you'll need to add this dependency for accessing FieldMaskUtil):
public static final FieldMask WITH_ID_AND_NAME =
FieldMaskUtil.fromFieldNumbers(User.class,
User.ID_FIELD_NUMBER,
User.NAME_FIELD_NUMBER);
then what I can do is merge this FieldMask with an existing object:
private static void log(User user, FieldMask fieldMask) {
User.Builder userWithMaskedFields = User.newBuilder();
FieldMaskUtil.merge(fieldMask, user, userWithMaskedFields);
System.out.println(userWithMaskedFields);
}
public static void main(String[] args) {
User user = User.newBuilder()
.setId("user")
.setName("a name")
.setPhoneNumber("12341234")
.build();
System.out.println("---Without FieldMask---");
System.out.println(user);
System.out.println("---With FieldMask---");
log(user, WITH_ID_AND_NAME);
}
This will give me the following output:
---Without FieldMask---
id: "user"
name: "a name"
phone_number: "12341234"
---With FieldMask---
id: "user"
name: "a name"
I hope that helps, let me know if you need more details, I can update my answer.
I'm using the GetSellerTransactionsCall from eBay Trading API to obtain transaction from an eBay Seller.
According to eBay Documentation this call is suppose to return a Seller object which contains a UserType with the following data:
Seller Object
User Type with Feedback Star Rating
I'm using the code below to execute Get Seller Transactions Call:
GetSellerTransactionsCall getSellerTransactionsCall = new GetSellerTransactionsCall();
getSellerTransactionsCall.setApiContext(ebayAPI.getAPIContext(profileID));
DetailLevelCodeType[] detailsLevels = new DetailLevelCodeType[1];
detailsLevels[0] = DetailLevelCodeType.RETURN_ALL;
getSellerTransactionsCall.setDetailLevel(detailsLevels);
getSellerTransactionsCall.setIncludeFinalValueFee(true);
TransactionType[] transactionTypes = getSellerTransactionsCall.getSellerTransactions();
UserType sellerAsUserType = getSellerTransactionsCall.getSeller();
System.out.println("Seller: " +sellerAsUserType ); // Prints null
FeedbackRatingStarCodeType feedbackRatingStarCodeType = sellerAsUserType.getFeedbackRatingStar();
System.out.println("Feedback Rating Star Code: " + feedbackRatingStarCodeType); // Prints null
I know the call itself is successful as I am able to iterate through all transactions of the given seller - so this is not a question of whether the call was successful or not.
Why are sellerAsUserType and feedbackRatingStarCodeType both null?
I am executing functions of a smart contract through web3j using the following code :
Credentials creds = getCredentialsFromPrivateKey("private-key");
RawTransactionManager manager = new RawTransactionManager(web3j, creds);
String contractAddress = "0x1278f8c858d799fe1010cfc0d1eeb56508243a4d";
BigInteger sum = new BigInteger("10000000000"); // amount you want to send
String data = encodeTransferData(sum);
BigInteger gasPrice = web3j.ethGasPrice().send().getGasPrice();
BigInteger gasLimit = BigInteger.valueOf(120000); // set gas limit here
EthSendTransaction transaction = manager.sendTransaction(gasPrice, gasLimit, contractAddress, data, null);
System.out.println(transaction.getTransactionHash());
It executes fine and the function is run, however i don't know how to read the output given by the contract, how can i read that output ?
this will return the hex value of the function call
private static List<Type> executeCall(Function function) throws IOException {
String encodedFunction = FunctionEncoder.encode(function);
org.web3j.protocol.core.methods.response.EthCall ethCall = web3j.ethCall(
Transaction.createEthCallTransaction(
"0x753ebAf6F6D5C2e3E6D469DEc5694Cd3Aa1A0c21", "0x47480bac30de77cd030b8a8dad2d6a2ecdb7f27a", encodedFunction),
DefaultBlockParameterName.LATEST)
.send();
String value = ethCall.getValue();
System.out.println(value);
System.out.println(FunctionReturnDecoder.decode(value, function.getOutputParameters()));
return FunctionReturnDecoder.decode(value, function.getOutputParameters());
}
Ethereum transaction hash is the unique id of the transaction. With this transaction hash, you can query the transaction status from the network.
The underlying JSON-RPC call is called eth_getTransactionReceipt. Here is Web3.js documentation.
If your smart contract emits events, you can also read those.
So i am working with Liferay 7/Oracle 11g and i try to copy existing organization roles of a specified subtype, rename them and then add those new roles to users that had the original Roles.
So getting roles by subtype works pretty straightforward,
the first Problem arises after i add the new role, i receive an error message when trying to view the new Role:
Someone may be trying to circumvent the permission checker: {companyId=20115, name=com.liferay.portal.kernel.model.Role, primKey=31701, scope=4}
the second Problem is getting the Users that have the original Organization Role as i can't find an existing Liferay class that delivers me that Information. From what i know its saved withing the USERGROUPROLE table, so i could read it from there with my own SQL select, but i would prefer if there was a Liferay class that provided that information.
List<Role> lRole = RoleLocalServiceUtil.getSubtypeRoles(String.valueOf(adoptFromYear));
for(Role role : lRole) {
long roleId = CounterLocalServiceUtil.increment();
Role newRole = RoleLocalServiceUtil.createRole(roleId);
newRole.setClassPK(roleId);
newRole.setCompanyId(role.getCompanyId());
newRole.setUserId(role.getUserId());
newRole.setUserName(role.getUserName());
newRole.setClassName(role.getClassName());
newRole.setTitle(role.getTitle());
newRole.setDescription(role.getDescription());
newRole.setCreateDate(new Date());
newRole.setType(role.getType());
newRole.setName(replaceOrAppendYear(role.getName(), newYear));
newRole.setSubtype(String.valueOf(newYear));
RoleLocalServiceUtil.addRole(newRole);
//assign Users that have base Role, the new Role
long[] aUserId = UserLocalServiceUtil.getRoleUserIds(role.getRoleId());
for(long userId : aUserId) {
RoleLocalServiceUtil.addUserRole(userId, newRole.getRoleId());
}
}
UPDATE:
I fixed the first problem by using another addRole method of UserLocalServiceUtil, code is now as following:
List<Role> lRole = RoleLocalServiceUtil.getSubtypeRoles(String.valueOf(adoptFromYear));
for(Role role : lRole) {
Role newRole = RoleLocalServiceUtil.addRole(role.getUserId(), Role.class.getName(),
CounterLocalServiceUtil.increment(), replaceOrAppendYear(role.getName(), newYear),
role.getTitleMap(), role.getDescriptionMap(), role.getType(),
String.valueOf(newYear), null);
//add User from base Role to new Role
long[] aUserId = UserLocalServiceUtil.getRoleUserIds(role.getRoleId());
//aUserId still empty
for(long userId : aUserId) {
RoleLocalServiceUtil.addUserRole(userId, newRole.getRoleId());
}
}
So the Problem of getting all User that have a certain Organization Role still exists.
So my solution to my problems is as following, i used the other addRole method to add a new Role and that also creates the additional entry in the db so there is no error message anymore.
On my second problem, i just use the liferay API to get all entries from UserGroupRole Table and then i filter all the entries via the roleId that i need. Not a nice solution, but in my case even with tens of thousands of entries (and thats generous for what i work on) the function will be called once a year so ¯\_(ツ)_/¯
So here is the solution:
List<Role> lRole = RoleLocalServiceUtil.getSubtypeRoles(String.valueOf(adoptFromYear));
for(Role role : lRole) {
Role newRole = RoleLocalServiceUtil.addRole(role.getUserId(), Role.class.getName(),
CounterLocalServiceUtil.increment(), replaceOrAppendYear(role.getName(), newYear),
role.getTitleMap(), role.getDescriptionMap(), role.getType(), String.valueOf(newYear), null);
//get all User - Group (Organization) - Role Objects and filter by Role
List<UserGroupRole> lUserGroupRole = UserGroupRoleLocalServiceUtil
.getUserGroupRoles(QueryUtil.ALL_POS, QueryUtil.ALL_POS).stream()
.filter(ugr -> ugr.getRoleId() == role.getRoleId()).collect(Collectors.toList());
//add new Role to all existing Users that had the adopted role
long[] roleIds = {newRole.getRoleId()};
for(UserGroupRole ugr : lUserGroupRole) {
UserGroupRoleLocalServiceUtil.addUserGroupRoles(ugr.getUserId(), ugr.getGroupId(), roleIds);
}
}
I am creating an application in which two players should have an opportunity to compete with each other in writing code.
For example, for now one player can initiate a session creation:
#PostMapping("/prepareSession")
public UUID prepareSession(#RequestParam("taskName") String taskName) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String currentPrincipalName = authentication.getName();
User playerOne = userService.findOne(currentPrincipalName);
Task task = taskService.findOne(taskName);
UUID sessionId = UUID.randomUUID();
sessionService.save(new Session(sessionId, playerOne, null, task));
return sessionId;
}
Then, this session id he needs to send to a player who he wants to compete.
And then second player inputs sessionId and gets a task description.
#GetMapping("/connect")
public Task connect(#RequestParam("sessionId") String sessionId) throws InterruptedException {
Session session = sessionService.findOne(sessionId);
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String currentPrincipalName = authentication.getName();
User playerSecond = userService.findOne(currentPrincipalName);
session.setPlayerSecond(playerSecond);
sessionService.save(session);
return session.getTask();
}
I wonder how to make the rest endpoint to wait until both players with same sessionId calls it and then notify them with the task description.
I want them to write code within a one session, with a one code timer.
Please suggest how I should do that
What you are looking for can be achieve like this
You could use a DeferredResult result and store it in a map until a user with the same sessionId joins. Ex
Map<String, DeferredResult<ResponseEntity<?>>> unconnected = new HashMap<String, DeferredResult<ResponseEntity<?>>>();
User one would call the connect prepareSessionAPI to receive the sessionId
User one would then call the connect API. The connet api would store this request/defferred result in the hashmap until user 2 joins. Ex
DeferredResult<Task> unconnectedTask = new DeferredResult<Task>();
unconnected.put(sessionId, unconnectedTask);
Now, user one's request would be stored in an in memory map until user two joins
User one would send the sessionId to user two
User two would call the connect API. The connect API would look for the session in the HashMap, and if it exists, it would perform the operations needed, then set the result of the deferred result. Ex
DeferredResult<Task> unconnectedTask = unconnected.get(sessionId);
if(unconnectedTask != null) {
// Do work
unconnectedTask.setResult(task);
} else {
// This is user one's request
}
Please note, this is pseudo code.
put this code both of method,
please import spring transnational jar
#Transactional(propagation =Propagation.REQUIRED,isolation=Isolation.SERIALIZABLE,readOnly=false,transactionManager="transactionManager")
if any issue inform