I am trying to implement google pay for the first time. I am having a challenge of how to specify the the gateway and gatewayMarchantId.
What I have is google console a account and don't know where to find this information.
private static JSONObject getTokenizationSpecification() throws JSONException {
JSONObject tokenizationSpecification = new JSONObject();
tokenizationSpecification.put("type", "PAYMENT_GATEWAY");
tokenizationSpecification.put(
"parameters",
new JSONObject()
.put("gateway", "example")
.put("gatewayMerchantId", "exampleGatewayMerchantId"));
return tokenizationSpecification;
}
what do I replace example and gatewayMerchantId with for my payment to work?
Google Pay uses your preferred gateway (see supported processors as of today) to process the payment. To do that, you need to specify the identification details of the gateway. You can typically find these inside of your processor/gateway's online console. You can see an example of how that looks like in the TokenizationSpecification reference.
If you also need production access to Google Pay, you can do that using the following form. The team will get back to you as quickly as possible after you do that. Once you have production access, you'll be granted a merchant identifier that you can use to perform payments in your production environment. Note that this identifier is Google Pay specific only, and you need it in addition to your gateway merchant identifier.
Hope it helps.
TL;DR W/o distributed private keys, how can I perform the auth flow for an Android app where the Identity Provider is Cognito itself, and the user only signs-up/in with email/password?
I'm developing an Android app in which I want the user to sign-in with "email and password" (NOT Google, Facebook, etc.) and then be able to download/upload objects from S3. I've worked with AWS for months, but all the while the sign-in functionality of my app was built on the sample app (the source of which has apparently changed substantially), which used the "AWSConfiguration" class to store:
AWS_MOBILEHUB_USER_AGENT
AMAZON_COGNITO_REGION
AMAZON_COGNITO_IDENTITY_POOL_ID
AMAZON_COGNITO_USER_POOL_ID
AMAZON_COGNITO_USER_POOL_CLIENT_ID
AMAZON_COGNITO_USER_POOL_CLIENT_SECRET
I need to implement sign-in and authorization to use AWS modules (like S3) WITHOUT embedding sensitive info.
It seems clear to me that this is going to be a "roll my own" situation so in going back to the good ol' start of the documentation on cognito, I'm already to confused as to why my "Email and password" sign-in model fits neither the bill of a "Public Provider" nor a "Developer Authenticated Identity":
From Mobile Hub:
In Cognito > MyUserPool > App Integration > App client settings it still appears as an identity provider of some kind (also it worked without me having to "enable" it):
The big question:
Is it possible to implement a sign-in flow where the user enters an email and a password, gets signed-in with Cognito, and the app has the necessary info to instantiate something like S3Object = new S3Client(credentialsProvider).getObject(...) without requiring a (separate/proxy) server to process private keys?
Also, are callback/sign-out URLs necessary for an app (and if so, why)?
Regarding your question on the obfuscation of service constants in the SDK, there is no standard method to do this - which offers guaranteed security. There are several third party and server based solutions. However Cognito does not recommend any specific technique for obfuscation.
To implement Sign-In and get credentials to access AWS resources, you can add Cognito as a Authentication Provider for your identity-pool. With this you will be able to use ID token vended by Cognito to access AWS resources. This code snippet shows how to use tokens issued by Cognito UserPools to access AWS resources in Android.
// Get id token from CognitoUserSession.
String idToken = cognitoUserSession.getIdToken().getJWTToken();
// Create a credentials provider, or use the existing provider.
CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(context, IDENTITY_POOL_ID, REGION);
// Set up as a credentials provider.
Map<String, String> logins = new HashMap<String, String>();
logins.put("cognito-idp.us-east-1.amazonaws.com/us-east-1_123456789", cognitoUserSession.getIdToken().getJWTToken());
credentialsProvider.setLogins(logins);
See this tutorial for further detail - http://docs.aws.amazon.com/cognito/latest/developerguide/tutorial-integrating-user-pools-android.html#tutorial-integrating-user-pools-getting-aws-credentials-android.
I'm using Stripe as a payment processor in my Android app and trying to charge a card as described by the documentation: https://stripe.com/docs/charges
My issue specifically is that it can not resolve Stripe.apiKey, or can not resolve symbol apiKey
The code that I'm implementing from the documentation:
// Set your secret key: remember to change this to your live secret key in production
// See your keys here: https://dashboard.stripe.com/account/apikeys
Stripe.apiKey = "sk_test_********************";//this is where i hit a wall
// Token is created using Stripe.js or Checkout!
// Get the payment token submitted by the form:
String token = request.getParameter("stripeToken");
// Charge the user's card:
Map<String, Object> params = new HashMap<String, Object>();
params.put("amount", 1000);
params.put("currency", "usd");
params.put("description", "Example charge");
params.put("source", token);
Charge charge = Charge.create(params);
I have also imported import com.stripe.android.*; at the top of my file.
In my Gradle file I have imported the Stripe libraries:
compile 'com.stripe:stripe-android:2.0.2'
Why isn't Android able to resolve Stripe.apiKey?
The code you provided is server-side Java code for creating a charge using a token. It is not meant to be used from an Android application.
A payment flow with Stripe is divided in two steps:
client-side, in your frontend code, you collect and tokenize the user's payment information (using Checkout or Stripe.js for a web application, or the iOS / Android SDKs for a native mobile application)
server-side, in your backend code, you use the resulting token in an API request, e.g. to create a charge or a customer object.
The first step is done with your publishable API key (pk_...). The second step is done with your secret API key (sk_...).
You must never share the secret API key with your frontend code, otherwise an attacker could retrieve it and use it to issue API requests on your behalf.
To solve Stripe.apikey cannot resolve, change Stripe.apiKey to
com.stripe.Stripe.apiKey = "Your secret";
Try: Stripe stripe = new Stripe("pk_test_6pRNASCoBOKtIshFeQd4XMUh");
For more info check out: https://stripe.com/docs/mobile/android#credit-card-form
I have to integrate stripe to receive payment. So, my basic concept is that there will be some service providers and the consumers. so the consumers will be able to book a service then pay for the same.I have already implemented the consumer side payment now I have to receive the payment from consumers. so in service provider side i need to configure the bank account for receiving the payment.
Let me explain the steps I'm going to follow
Listing the supported banks by stripe
Blockers
1.1) I couldn't find any doc for listing the stripe supported bank in theire doc
Select any bank then add the credentiols for the choosen
Save the token for the particular
Verify account
Getting paid from consumers
Pl. help me any experienced one if any flaw in my understandings & help me to overcome the blockers
Let me explain the steps for adding an account to receive payment using stripe.
there are two ways to verify your account
Using Plaid
Manually collecting and verifying bank accounts
Here I illustrating the second solution
Step 1
The first thing we have to do is that collecting user account details to create a stripe token which need to send to our server.
Setting up token metadata
Map<String, Object> tokenParams = new HashMap<String, Object>();
Map<String, Object> bank_accountParams = new HashMap<String, Object>();
bank_accountParams.put("country", "US");
bank_accountParams.put("currency", "usd");
bank_accountParams.put("account_holder_name", "name");
bank_accountParams.put("account_holder_type", "individual");
bank_accountParams.put("routing_number", "number");
bank_accountParams.put("account_number", "a/c no");
tokenParams.put("bank_account", bank_accountParams);
Create token
Token token = null;
try {
token = Token.create(params[0]);
} catch (AuthenticationException e) {
error = e.getMessage();
e.printStackTrace();
}
Send token id to server for later verification
token.getId()
Step 2
Receiving a representative token in return. Once you have that, attach it to a Stripe customer in your account
// Set your secret key: remember to change this to your live secret key in production
// See your keys here: https://dashboard.stripe.com/account/apikeys
Stripe.apiKey = "sk_test_BQokikJOvBiI2HlWgH4olfQ2";
// Get the bank token submitted by the form
String tokenID = request.getParameter("stripeToken");
// Create a Customer
Map<String, Object> customerParams = new HashMap<String, Object>();
customerParams.put("source", tokenID);
customerParams.put("description", "Example customer");
Customer customer = Customer.create(customerParams);
After adding the bank account to a customer, it needs to be verified. When using Stripe without Plaid, verification is done via two small deposits into the bank account that Stripe will automatically send. These deposits will take 1-2 business days to appear on the customer’s online statement. The statement description for these deposits will be VERIFICATION. Your customer will need to relay the value of the two deposits to you.
When accepting these values, be sure to note that there is a limit of 10 failed verification attempts. Once this limit has been crossed, the bank account will be unable to be verified. Careful messaging about what these microdeposits are and how they are used can help your end customers avoid this issue. Once you have these values, you can verify the bank account:
// Set your secret key: remember to change this to your live secret key in production
// See your keys here: https://dashboard.stripe.com/account/apikeys
Stripe.apiKey = "sk_test_BQokikJOvBiI2HlWgH4olfQ2";
// get the existing bank account
Customer customer = Customer.retrieve("cus_7iLOlPKxhQJ75a");
ExternalAccount source = customer.getSources().retrieve("ba_17SHwa2eZvKYlo2CUx7nphbZ");
// verify the account
Map params = new HashMap<String, Object>();
ArrayList amounts = new ArrayList();
amounts.add(32);
amounts.add(45);
params.put("amounts", amounts);
source.verify(params);
Once the bank account is verified, you can make charges against it.
Reference
Stripe ACH
Creating Charges
Samples using stripe
I have a simple app (needs user login with account). I provide some premium features for paid users, like more news content.
I need to record if the user has bought this item in my server database. When I provide data content to user's device, I can then check the user's status, and provide different content for paid user.
I checked the official Trivialdrive sample provided by Google, it does not provide any sample code for server-side verification, here are my questions.
I found the sample use my app's public key inside to verify purchase, it looks not good, I think I can just move the verification process to my server combined with user login credentials to see whether the user purchase completed, and then update the database.
Also there is purchase API I can use to query, what I need is to pass the user's purchaseToken into server.
I am not sure what method I should take to verify the user's purchase, and mark the user's status in my database, maybe both?
And I am afraid there is a situation, if a user bought this item from google play, but for some reason, just in that time, when my app launched verification to my server, the network connection is down or my own server is down, user just paid the money in google play but I did not record the purchase in my server? What should I do, How can I deal with this situation.
It sounds what you're looking for is a way to check if the user has premium features enabled on their account, so this is where I would start;
Ensure there is a flag of some sort on your database indicating if the user has premium features and include that in the API response payload when requesting account info. This flag will be your primary authority for "premium features".
When a user makes an in-app purchase, cache the details (token, order id, and product id) locally on the client (i.e the app) then send it to your API.
Your API should then send the purchaseToken to the Google Play Developer API for validation.
A few things might happen from here:
The receipt is valid, your API responds to the client with a 200 Ok status code
The receipt is invalid, your API responds to the client with a 400 Bad Request status code
Google Play API is down, your API responds with a 502 Bad Gateway status code
In the case of 1. or 2. (2xx or 4xx status codes) your client clears the cache of purchase details because it doesn't need it anymore because the API has indicated that it has been received.
Upon a successful validation (case 1.), you should set the premium flag to true for the user.
In the case of 3. (5xx status code) or a network timeout the client should keep trying until it receives a 2xx or 4xx status code from your API.
Depending on your requirements, you could make it wait a few seconds before sending again or just send the details to your API when ever the app is launched again or comes out of background if the purchase details are present on the app cache.
This approach should take care of network timeouts, servers being unavailable, etc.
There are now a few questions you need to consider:
What should happen immediately after a purchase? Should the app wait until validation is successful before providing premium content or should it tentatively grant access and take it away if the validation fails?
Granting tentative access to premium features smooths the process for a majority of your users, but you will be granting access to a number of fraudulent users too while your API validates the purchaseToken.
To put this in another way: Purchase is valid until proven fraudulent or; fraudulent until proven valid?
In order to identify if the user still has a valid subscription when their subscription period comes up for renewal, you will need to schedule a re-validation on the purchaseToken to run at the expiryTimeMillis that was returned in the result.
If the expiryTimeMillis is in the past, you can set the premium flag to false. If it's in the future, re-schedule it again for the new expiryTimeMillis.
Lastly, to ensure the user has premium access (or not), your app should query your API for the users details on app launch or when it comes out of background.
The documentation on this is confusing and weirdly verbose with the things that are almost inconsequential while leaving the actually important documentation almost unlinked and super hard to find. This should work great on most popular server platform that can run the google api client libraries, including Java, Python, .Net, and NodeJS, among others. Note: I've tested only the Python api client as shown below.
Necessary steps:
Make an API project, from the API Access link in your Google Play console
Make a new service account, save the JSON private key that gets generated. You'll need to take this file to your server.
Press Done in the Play console's service account section to refresh and then grant access to the service account
Go get a google api client library for your server platform from https://developers.google.com/api-client-library
Use your particular platform's client library to build a service interface and directly read the result of your purchase verification.
You do not need to bother with authorization scopes, making custom requests calls, refreshing access tokens, etc. the api client library takes care of everything. Here's a python library usage example to verify a subscription:
First, install the google api client in your pipenv like this:
$ pipenv install google-api-python-client
Then you can set up api client credentials using the private key json file for authenticating the service account.
credentials = service_account.Credentials.from_service_account_file("service_account.json")
Now you can verify subscription purchases or product purchases using the library, directly.
#Build the "service" interface to the API you want
service = googleapiclient.discovery.build("androidpublisher", "v3", credentials=credentials)
#Use the token your API got from the app to verify the purchase
result = service.purchases().subscriptions().get(packageName="your.app.package.id", subscriptionId="sku.name", token="token-from-app").execute()
#result is a python object that looks like this ->
# {'kind': 'androidpublisher#subscriptionPurchase', 'startTimeMillis': '1534326259450', 'expiryTimeMillis': '1534328356187', 'autoRenewing': False, 'priceCurrencyCode': 'INR', 'priceAmountMicros': '70000000', 'countryCode': 'IN', 'developerPayload': '', 'cancelReason': 1, 'orderId': 'GPA.1234-4567-1234-1234..5', 'purchaseType': 0}
The documentation for the platform service interface for the play developer API is not linked in an easy to find way, for some it is downright hard to find. Here are the links for the popular platforms that I found:
Python | Java | .NET | PHP | NodeJS (Github TS) | Go (Github JSON)
Complete example of using Google API Client Library for PHP:
Setup your Google Project and access to Google Play for your service account as described in Marc's answer here https://stackoverflow.com/a/35138885/1046909.
Install the library: https://developers.google.com/api-client-library/php/start/installation.
Now you are able to verify your receipt the following way:
$client = new \Google_Client();
$client->setAuthConfig('/path/to/service/account/credentials.json');
$client->addScope('https://www.googleapis.com/auth/androidpublisher');
$service = new \Google_Service_AndroidPublisher($client);
$purchase = $service->purchases_subscriptions->get($packageName, $productId, $token);
After that $purchase is instance of Google_Service_AndroidPublisher_SubscriptionPurchase
$purchase->getAutoRenewing();
$purchase->getCancelReason();
...
You can try using Purchases.subscriptions: get server-side. It takes packageName, subscriptionId and token as paramaters and requires authorization.
Checks whether a user's subscription purchase is valid and returns its
expiry time.
If successful, this method returns a Purchases.subscriptions resource in the response body.
I answer to this concern
the network connection is down or my own server is down, user just
paid the money in google play but I did not record the purchase in my
server? What should I do, How can I deal with this situation.
The situation is:
User purchases 'abc' item using google play service -> return OK -> fail to verify with server for some reasons such as no Internet connection.
Solution is:
On the client side, before showing the 'Google Wallet' button, you check if the 'abc' item is already owned.
if yes, verify with server again
if no, show the 'Google Wallet' button.
Purchase purchase = mInventory.getPurchase('abc');
if (purchase != null) // Verify with server
else // show Google Wallet button
https://developer.android.com/google/play/billing/billing_reference.html#getSkuDetails
Marc Greenstock's answer is definitely enlightening, a few things to pay attention though which took me a long time to figure out (at least way more time than I expected):
I had to check "Enable G Suite Domain-wide Delegation" on Service Account settings. Without this I kept getting this error: "The current user has insufficient permissions to perform the requested operation"
Image with Enable G Suite Domain-wide Delegation option checked
For testing purposes you can create a JWT token for your service account here, just don't forget to select RS256 Algorithm.
The public key is the "private_key_id" from your downloaded JSON file. It also has the following format:
-----BEGIN PUBLIC KEY-----
{private_key_id}
-----END PUBLIC KEY-----
The private key is the "private_key" from your downloaded JSON file
The required claims for the JWT generation are described here.
Confused about what exactly a JWT Token is and how it is assembled? Don't be ashamed, check this link. Odds are you are just like me and took a long time to bother looking for what exactly it is, it is (way) simpler than it looks.
I had some serious problems using the suggested google API python library, but implementing the communication from scratch is not so hard.
First of all you have to create a service account at Google Play Console as described in all answers and get the JSON file containing the private key. Save it to your server.
Then use the following code. No need to obtain the google API client library. You only need the following (very common) python libraries Requests and Pycrypto
import requests
import datetime
import json
import base64
from Crypto.Signature import PKCS1_v1_5 as Signature_pkcs1_v1_5
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
jwtheader64 = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9"
#SERVICE_ACCOUNT_FILE: full path to the json key file obtained from google
with open(SERVICE_ACCOUNT_FILE) as json_file:
authinfo = json.load(json_file)
packageName = #your package name
product = #your inapp id
token = #your purchase token
#create the JWT to use for authentication
now = datetime.datetime.now()
now1970 = (now - datetime.datetime(1970,1,1)).total_seconds()
jwtclaim = {"iss":authinfo["client_email"],"scope":"https://www.googleapis.com/auth/androidpublisher","aud": "https://oauth2.googleapis.com/token","iat":now1970,"exp":now1970+1800,"sub":authinfo["client_email"]}
jwtclaimstring = json.dumps(jwtclaim).encode(encoding='UTF-8')
jwtclaim64 = base64.urlsafe_b64encode(jwtclaimstring).decode(encoding='UTF-8')
tosign = (jwtheader64+"."+jwtclaim64).encode(encoding='UTF-8')
#sign it with your private key
private = authinfo["private_key"].encode(encoding='UTF-8')
signingkey = RSA.importKey(private)
signer = Signature_pkcs1_v1_5.new(signingkey)
digest = SHA256.new()
digest.update(tosign)
signature = signer.sign(digest)
res = base64.urlsafe_b64encode(signature).decode(encoding='UTF-8')
#send it to Google authentication server to obtain your access token
headers = {'Content-Type': 'mapplication/x-www-form-urlencoded'}
payload = "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion="+jwtheader64+"."+jwtclaim64+"."+res
r = requests.post("https://oauth2.googleapis.com/token",headers=headers,data=payload)
if r.status_code == 200:
authdata = json.loads(r.text)
accesstoken = authdata['access_token']
bearerheader = {'Authorization':'Bearer '+authdata['access_token']}
#Now you have at last your authentication token, so you can use it to make calls. In this example we want to verify a subscription
url = "https://androidpublisher.googleapis.com/androidpublisher/v3/applications/"+packageName+"/purchases/subscriptions/"+product+"/tokens/"+token
subscription = requests.get(url,headers=bearerheader)
the network connection is down or my own server is down,
You don't have to think like this.
Client knows own's consume product. so, client can send all tokens back to the server.
Just re-check token with produce id and transaction id.
And Server checks consume product.
if you fail check
make UI button client can re-send token.
server re-check token for items.
It's done.