package com.library.util;

import com.google.gson.Gson;
import com.paygo24.v3.protocol.*;
import org.tempuri.PayGoService;
import org.tempuri.PayGoServiceSoap;
import org.tempuri.SendRequest;
import org.tempuri.SendRequestResponse;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.Duration;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.namespace.QName;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URL;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.UUID;

/**
 * Description: Paygo24手机充值工具类 Company: youjiang
 * <p>
 * 接口文档地址: http://developers.paygo24.com/api-dealers-api-v3
 *
 * @author Kwum
 * @version 1.0
 * @date 2017年9月8日 下午4:58:14
 */

public class Paygo24Utils {

	/** 注册成功返回的状态码 */
	private static final String CORRECT_REGISTER_STATE = "0";
	/** 注册成功返回的状态码 重试 */
	private static final String CORRECT_REGISTER_TRY = "3";
	/** 充值成功返回的状态码 */
	private static final String CORRECT_PAYMENT_STATE = "5";
	/** 充值还没有处理完返回的状态码 */
	private static final String CORRECT_PAYMENT_STATE_ACCEPTED = "0";
	/** 充值还没有处理完返回的状态码 */
	private static final String CORRECT_PAYMENT_STATE_WAS = "3";
	/**
	 * 充值还没有处理完返回的状态码
	 */
	private static final String CORRECT_PAYMENT_STATE_DELAYED = "4";
	/**
	 * 充值还没有处理完返回的状态码
	 */
	private static final String CORRECT_PAYMENT_STATE_PROVIDER = "6";

	/**
	 * 处理成功返回给调用者的状态码
	 */
	public static final String SUCCESS = "SUCCESS";
	/**
	 * 配置文件中的paygo24 id
	 */
	private static Integer POINT_ID = 451717;

	/**
	 * 配置文件中的paygo24 密码
	 */
	private static String PASSWORD = "iWoQosQ+z9YFXqKuyPyRNg==";

	/**
	 * 付款后余额
	 */
	private BigDecimal availableBalance;
	/**
	 * 当前账号余额
	 */
	private BigDecimal currentBalance;
	/*** 重新查询的次数 ****/
	private Integer count;

	public static void main(String[] args) {
		Paygo24Utils paygo24Utils = new Paygo24Utils();
		String result = paygo24Utils.payment("098375667", 2, new BigDecimal(1.0));
		System.out.println("result："+result);
	}

	/**
	 * 充值接口
	 * 
	 * @param phone
	 *            手机号码
	 * @param serviceId
	 *            服务商id
	 * @param money
	 *            充值金额
	 * @return 成功返回SUCCESS，失败则返回失败原因
	 * @author kwum
	 */
	public String payment(String phone, Integer serviceId, BigDecimal money) {

		try {

			PayGoService service;
			service = new PayGoService(new URL("https://processing2.paygo24.com/paygoservice.asmx"),
					QName.valueOf("{http://tempuri.org/}PayGoService"));
			PayGoServiceSoap soap = service.getPayGoServiceSoap();
			SendRequest sendRequest = new SendRequest();
			sendRequest.setPointId(POINT_ID);
			sendRequest.setPassword(PASSWORD);

			/** RegisterCheckRequest */
			RegisterCheckRequest registerCheckRequest = new RegisterCheckRequest();
			String uuId = UUID.randomUUID().toString();
			registerCheckRequest.setId(uuId);
			registerCheckRequest.setService(BigInteger.valueOf(serviceId));
			ArrayOfParameter ap = new ArrayOfParameter();
			Parameter account = new Parameter();
			account.setName("account");
			account.setValue(phone);
			ap.getParameter().add(account);
			registerCheckRequest.setPaymentParameters(ap);
			sendRequest.setRequest(registerCheckRequest);
			SendRequestResponse response = soap.sendRequest(sendRequest);
			System.out.println("RegisterCheckRequest response:" + new Gson().toJson(response));

			if (response.getSendRequestResult() instanceof RegisterCheckResponse) {
				// Success. You can get result
				Duration duaration = ((RegisterCheckResponse) response.getSendRequestResult())
						.getGetCheckResultTimeout();
				long millis = duaration.getTimeInMillis(new Date());
				try {
					// wait before get result
					Thread.sleep(millis);

					/** GetCheckResultRequest */
					GetCheckResultRequest gcrr = new GetCheckResultRequest();
					gcrr.setId(uuId);
					sendRequest.setRequest(gcrr);
					response = soap.sendRequest(sendRequest);

					System.out.println(new Gson().toJson(response));
					if (response.getSendRequestResult() instanceof GetCheckResultResponse) {
						// Process results
						GetCheckResultResponse gcresp = ((GetCheckResultResponse) response.getSendRequestResult());
						if (CORRECT_REGISTER_STATE.equals(gcresp.getState())) {// 注册成功，执行充值流程
							return paymentMain(uuId, serviceId, money, ap, soap, sendRequest);
						} else if (CORRECT_REGISTER_TRY.equals(gcresp.getState())) {
							return checkResult(response, soap, sendRequest, uuId, serviceId, money, ap, millis);
						} else {
							return "GetCheckResultResponse  " + gcresp.getState() + " : " + gcresp.getDescription();
						}
					} else {
						// Process error (ErrorResponse)
						ErrorResponse errorResponse = (ErrorResponse) response.getSendRequestResult();
						return "GetCheckResultResponse  " + errorResponse.getError().getNumber() + " : "
								+ errorResponse.getError().getDescription();
					}
				} catch (Exception e) {
					e.printStackTrace();
					// Logger.getLogger(Paygo24Utils.class.getName()).log(Level.SEVERE,
					// null, e);
					return "System error. GetCheckResultRequest ";
				}
			} else {
				// Process error (ErrorResponse)
				ErrorResponse errorResponse = (ErrorResponse) response.getSendRequestResult();
				return "RegisterCheckRequest  " + errorResponse.getError().getNumber() + " : "
						+ errorResponse.getError().getDescription();
			}
		} catch (Exception e) {
			e.printStackTrace();
			// Logger.getLogger(Paygo24Utils.class.getName()).log(Level.SEVERE,
			// null, e);
			return "Connect Paygo24 failed. SendRequestResponse";
		}
	}

	private String checkResult(SendRequestResponse response, PayGoServiceSoap soap, SendRequest sendRequest,
			String uuId, Integer serviceId, BigDecimal money, ArrayOfParameter ap, long millis)
			throws InterruptedException {
		Thread.sleep(1000 * 2);
		/** GetCheckResultRequest */
		response = soap.sendRequest(sendRequest);
		if (response.getSendRequestResult() instanceof GetCheckResultResponse) {
			// Process results
			GetCheckResultResponse gcresp = ((GetCheckResultResponse) response.getSendRequestResult());
			if (CORRECT_REGISTER_STATE.equals(gcresp.getState())) {// 注册成功，执行充值流程

				return paymentMain(uuId, serviceId, money, ap, soap, sendRequest);
			} else if (CORRECT_REGISTER_TRY.equals(gcresp.getState())) {
				return checkResult(response, soap, sendRequest, uuId, serviceId, money, ap, millis);
			} else {
				return "GetCheckResultResponse  " + gcresp.getState() + " : " + gcresp.getDescription();
			}
		} else {
			// Process error (ErrorResponse)
			ErrorResponse errorResponse = (ErrorResponse) response.getSendRequestResult();
			return "GetCheckResultResponse  " + errorResponse.getError().getNumber() + " : "
					+ errorResponse.getError().getDescription();
		}
	}

	/**
	 * 充值主要流程
	 * 
	 * @param uuId
	 * @param serviceId
	 * @param money
	 *            金额
	 * @param ap
	 *            参数对
	 * @param soap
	 * @param sendRequest
	 * @return 成功返回SUCCESS，失败则返回失败原因
	 * @author kwum
	 */
	private String paymentMain(String uuId, Integer serviceId, BigDecimal money, ArrayOfParameter ap,
			PayGoServiceSoap soap, SendRequest sendRequest) {

		/** SendPaymentRequest */
		SendPaymentRequest spr = new SendPaymentRequest();
		spr.setId(uuId);
		spr.setService(BigInteger.valueOf(serviceId));
		GregorianCalendar gcal = new GregorianCalendar();
		gcal.setTime(new Date());
		XMLGregorianCalendar xgcal = null;
		try {
			xgcal = DatatypeFactory.newInstance().newXMLGregorianCalendar(gcal);
		} catch (DatatypeConfigurationException e) {
			e.printStackTrace();
			// Logger.getLogger(Paygo24Utils.class.getName()).log(Level.SEVERE,
			// null, e);
			return "System error.";
		}
		spr.setTime(xgcal);
		spr.setValue(money);
		spr.setCommission(BigDecimal.valueOf(0));
		spr.setCurrency("USD");
		spr.setPaymentParameters(ap);
		sendRequest.setRequest(spr);
		SendRequestResponse response = soap.sendRequest(sendRequest);
		System.out.println(new Gson().toJson(response));
		if (response.getSendRequestResult() instanceof SendPaymentResponse) {
			// Success. You can get result
			Duration duaration = ((SendPaymentResponse) response.getSendRequestResult()).getCheckStateTimeout();
			long millis = duaration.getTimeInMillis(new Date());
			availableBalance = ((SendPaymentResponse) response.getSendRequestResult()).getAvailableBalance();
			currentBalance = ((SendPaymentResponse) response.getSendRequestResult()).getCurrentBalance();
			try {
				// wait before get result
				Thread.sleep(millis);

				/** CheckStatusRequest */
				CheckStatusRequest csr = new CheckStatusRequest();
				csr.setId(uuId);
				sendRequest.setRequest(csr);
				response = soap.sendRequest(sendRequest);

				System.out.println(new Gson().toJson(response));

				if (response.getSendRequestResult() instanceof CheckStatusResponse) {
					// Process results
					CheckStatusResponse csresp = ((CheckStatusResponse) response.getSendRequestResult());
					if (CORRECT_PAYMENT_STATE.equals(csresp.getState())) {// 充值成功
						System.out.println("充值成功");
						return SUCCESS;
					} else if (CORRECT_PAYMENT_STATE_ACCEPTED.equals(csresp.getState())
							|| CORRECT_PAYMENT_STATE_WAS.equals(csresp.getState())
							|| CORRECT_PAYMENT_STATE_DELAYED.equals(csresp.getState())
							|| CORRECT_PAYMENT_STATE_PROVIDER.equals(csresp.getState())) {
						count = 1;
						return paymentCheck(response, soap, sendRequest);
					} else {
						return "CheckStatusResponse  " + csresp.getState() + " : " + csresp.getStateComment();
					}
				} else {
					// Process error (ErrorResponse)
					ErrorResponse errorResponse = (ErrorResponse) response.getSendRequestResult();
					return "CheckStatusResponse  " + errorResponse.getError().getNumber() + " : "
							+ errorResponse.getError().getDescription();
				}
			} catch (Exception e) {
				e.printStackTrace();
				// Logger.getLogger(Paygo24Utils.class.getName()).log(Level.SEVERE,
				// null, e);
				return "System error. CheckStatusRequest";
			}
		} else {

			// Process error (ErrorResponse)
			ErrorResponse errorResponse = (ErrorResponse) response.getSendRequestResult();
			return "SendPaymentRequest  " + errorResponse.getError().getNumber() + " : "
					+ errorResponse.getError().getDescription();
		}
	}

	/***
	 * 
	 * Description:查询充值状态
	 * 
	 * @author feng
	 * @date 2017年9月12日 下午4:46:46
	 * @version 1.0
	 * @return
	 * @throws InterruptedException
	 */
	private String paymentCheck(SendRequestResponse response, PayGoServiceSoap soap, SendRequest sendRequest)
			throws InterruptedException {

		Thread.sleep(1000 * 5);

		/** CheckStatusRequest */

		response = soap.sendRequest(sendRequest);
		if (response.getSendRequestResult() instanceof CheckStatusResponse) {
			// Process results
			CheckStatusResponse csresp = ((CheckStatusResponse) response.getSendRequestResult());
			if (CORRECT_PAYMENT_STATE.equals(csresp.getState())) {// 充值成功
				return SUCCESS;
			} else if ((CORRECT_PAYMENT_STATE_ACCEPTED.equals(csresp.getState())
					|| CORRECT_PAYMENT_STATE_WAS.equals(csresp.getState())
					|| CORRECT_PAYMENT_STATE_DELAYED.equals(csresp.getState())
					|| CORRECT_PAYMENT_STATE_PROVIDER.equals(csresp.getState())) && count <= 6) {
				count++;
				return paymentCheck(response, soap, sendRequest);

			} else {
				return "CheckStatusResponse  " + csresp.getState() + " : " + csresp.getStateComment();
			}
		} else {
			// Process error (ErrorResponse)
			ErrorResponse errorResponse = (ErrorResponse) response.getSendRequestResult();
			return "SendPaymentRequest  " + errorResponse.getError().getNumber() + " : "
					+ errorResponse.getError().getDescription();
		}
		

	}

	public BigDecimal getAvailableBalance() {
		return availableBalance;
	}

	public BigDecimal getCurrentBalance() {
		return currentBalance;
	}
}
