// Path: src/main/java/com/lookfirst/wepay/api/Token.java
// @Data
// public class Token implements Serializable {
// 	private static final long serialVersionUID = 1L;
// 
// 	/** The unique user ID of the user */
// 	private String userId;
// 	/** The access token that you can use to make calls on behalf of the user */
// 	private String accessToken;
// 	/** The token type - for now only "BEARER" is supported */
// 	private String tokenType;
// 	/** How much time till the access_token expires. If NULL or not present, the access token will be valid until the user revokes the access_token */
// 	private String expiresIn;
// }
// 
// Path: src/main/java/com/lookfirst/wepay/api/req/TokenRequest.java
// @Data
// @EqualsAndHashCode(callSuper=false)
// public class TokenRequest extends WePayRequest<Token> {
// 
// 	public static final String ENDPOINT = "/oauth2/token";
// 
// 	/** Yes	The client ID issued to the app by WePay - see your client ID on your app screen */
// 	private Long clientId;
// 	/** Yes	The uri the user will be redirected to after authorization. Must be the same as passed in /v2/oauth2/authorize */
// 	private String redirectUri;
// 	/** Yes	The client secret issued to the app by WePay - see your client secret on your app screen */
// 	private String clientSecret;
// 	/** Yes	The code returned by /v2/oauth2/authorize */
// 	private String code;
// 
// 	/** */
// 	@Override
// 	public String getEndpoint() {
// 		return "/oauth2/token";
// 	}
// 
// }
// 
// Path: src/main/java/com/lookfirst/wepay/api/req/WePayRequest.java
// public abstract class WePayRequest<T> {
// 	@JsonIgnore
// 	public abstract String getEndpoint();
// }
// 
// Path: src/main/java/com/lookfirst/wepay/util/DataProvider.java
// public interface DataProvider {
// 	InputStream getData(String uri, String postJson, String token) throws IOException;
// }


import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.lookfirst.wepay.api.Token;
import com.lookfirst.wepay.api.req.TokenRequest;
import com.lookfirst.wepay.api.req.WePayRequest;
import com.lookfirst.wepay.util.DataProvider;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.ParameterizedType;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;
	 * @param scopes             List of scope fields for which your application wants access
	 * @param redirectUri      Where user goes after logging in at WePay (domain must match application settings)
	 * @param userName  user_name,user_email which will be pre-filled on login form, state to be returned in querystring of redirect_uri
	 * @return string URI to which you must redirect your user to grant access to your application
	 */
	public String getAuthorizationUri(List<Scope> scopes, String redirectUri, String state, String userName, String userEmail) {
		// this method must use www instead of just naked domain for security reasons.
		String host = key.isProduction() ? "https://www.wepay.com" : "https://stage.wepay.com";
		String uri = host + "/v2/oauth2/authorize?";

		uri += "client_id=" +  urlEncode(key.getClientId()) + "&";
		uri += "redirect_uri=" +  urlEncode(redirectUri) + "&";
		uri += "scope=" + urlEncode(StringUtils.join(scopes, ","));
		if (state != null || userName != null || userEmail != null)
			uri += "&";
		uri += state != null ? "state=" +  urlEncode(state) + "&" : "";
		uri += userName != null ? "user_name=" +  urlEncode(userName) + "&" : "";
		uri += userEmail != null ? "user_email=" +  urlEncode(userEmail) : "";

		return uri;
	}

	/**
	 * Exchange a temporary access code for a (semi-)permanent access token
	 * @param code          'code' field from query string passed to your redirect_uri page
	 * @param redirectUrl  Where user went after logging in at WePay (must match value from getAuthorizationUri)
	 * @return json {"user_id":"123456","access_token":"1337h4x0rzabcd12345","token_type":"BEARER"}
	 */
	public Token getToken(String code, String redirectUrl) throws IOException, WePayException {

// Path: src/main/java/com/lookfirst/wepay/api/Token.java
// @Data
// public class Token implements Serializable {
// 	private static final long serialVersionUID = 1L;
// 
// 	/** The unique user ID of the user */
// 	private String userId;
// 	/** The access token that you can use to make calls on behalf of the user */
// 	private String accessToken;
// 	/** The token type - for now only "BEARER" is supported */
// 	private String tokenType;
// 	/** How much time till the access_token expires. If NULL or not present, the access token will be valid until the user revokes the access_token */
// 	private String expiresIn;
// }
// 
// Path: src/main/java/com/lookfirst/wepay/api/req/TokenRequest.java
// @Data
// @EqualsAndHashCode(callSuper=false)
// public class TokenRequest extends WePayRequest<Token> {
// 
// 	public static final String ENDPOINT = "/oauth2/token";
// 
// 	/** Yes	The client ID issued to the app by WePay - see your client ID on your app screen */
// 	private Long clientId;
// 	/** Yes	The uri the user will be redirected to after authorization. Must be the same as passed in /v2/oauth2/authorize */
// 	private String redirectUri;
// 	/** Yes	The client secret issued to the app by WePay - see your client secret on your app screen */
// 	private String clientSecret;
// 	/** Yes	The code returned by /v2/oauth2/authorize */
// 	private String code;
// 
// 	/** */
// 	@Override
// 	public String getEndpoint() {
// 		return "/oauth2/token";
// 	}
// 
// }
// 
// Path: src/main/java/com/lookfirst/wepay/api/req/WePayRequest.java
// public abstract class WePayRequest<T> {
// 	@JsonIgnore
// 	public abstract String getEndpoint();
// }
// 
// Path: src/main/java/com/lookfirst/wepay/util/DataProvider.java
// public interface DataProvider {
// 	InputStream getData(String uri, String postJson, String token) throws IOException;
// }


// Path: src/main/java/com/lookfirst/wepay/WePayApi.java
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.lookfirst.wepay.api.Token;
import com.lookfirst.wepay.api.req.TokenRequest;
import com.lookfirst.wepay.api.req.WePayRequest;
import com.lookfirst.wepay.util.DataProvider;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.ParameterizedType;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.List;

	 * @param scopes             List of scope fields for which your application wants access
	 * @param redirectUri      Where user goes after logging in at WePay (domain must match application settings)
	 * @param userName  user_name,user_email which will be pre-filled on login form, state to be returned in querystring of redirect_uri
	 * @return string URI to which you must redirect your user to grant access to your application
	 */
	public String getAuthorizationUri(List<Scope> scopes, String redirectUri, String state, String userName, String userEmail) {
		// this method must use www instead of just naked domain for security reasons.
		String host = key.isProduction() ? "https://www.wepay.com" : "https://stage.wepay.com";
		String uri = host + "/v2/oauth2/authorize?";

		uri += "client_id=" +  urlEncode(key.getClientId()) + "&";
		uri += "redirect_uri=" +  urlEncode(redirectUri) + "&";
		uri += "scope=" + urlEncode(StringUtils.join(scopes, ","));
		if (state != null || userName != null || userEmail != null)
			uri += "&";
		uri += state != null ? "state=" +  urlEncode(state) + "&" : "";
		uri += userName != null ? "user_name=" +  urlEncode(userName) + "&" : "";
		uri += userEmail != null ? "user_email=" +  urlEncode(userEmail) : "";

		return uri;
	}

	/**
	 * Exchange a temporary access code for a (semi-)permanent access token
	 * @param code          'code' field from query string passed to your redirect_uri page
	 * @param redirectUrl  Where user went after logging in at WePay (must match value from getAuthorizationUri)
	 * @return json {"user_id":"123456","access_token":"1337h4x0rzabcd12345","token_type":"BEARER"}
	 */
	public Token getToken(String code, String redirectUrl) throws IOException, WePayException {

		TokenRequest request = new TokenRequest();