package cn.hmsoft.pay.impl;

import java.time.LocalDateTime;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;

import cn.hmsoft.helper.BeanHelper;
import cn.hmsoft.helper.JsonHelper;
import cn.hmsoft.helper.LocalDateHelper;
import cn.hmsoft.helper.StringHelper;
import cn.hmsoft.log.LogHelper;
import cn.hmsoft.pay.constants.BillProcessResult;
import cn.hmsoft.pay.constants.PayBillStatus;
import cn.hmsoft.pay.data.dao.PayBillDao;
import cn.hmsoft.pay.data.model.PayBill;
import cn.hmsoft.pay.data.model.PayBillAlipay;
import cn.hmsoft.pay.impl.alipay.AliPayOrderDetailRequest;
import cn.hmsoft.pay.impl.alipay.AliPayOrderNoticeResponse;

public class PayAliPayChannelImpl extends PayChannelAbstract {

	private AlipayClient alipayClient;
	private String gatewayUrl;
	private String app_id;
	private String merchant_private_key;
	private String charset;
	private String alipay_public_key;
	private String sign_type;
	// private final String METHOD_PAY = "alipay.trade.page.pay";

	@Override
	protected boolean init() throws Exception {
		gatewayUrl = this.getChannel().getPay_url();
		app_id = this.getPayMerchantChannel().getBank_merchant_id();
		merchant_private_key = this.getPayMerchantChannel().getPrivate_key_path();
		charset = "utf-8";
		alipay_public_key = this.getPayMerchantChannel().getPublic_key_path();
		sign_type = "RSA2";
		// 获得初始化的AlipayClient;
		alipayClient = new DefaultAlipayClient(gatewayUrl, app_id, merchant_private_key, "json", charset,
				alipay_public_key, sign_type);

		return true;
	}

	@Override
	public String makeBillNo(PayBill bill) {
		String v = StringHelper.leftPadding(bill.getBusiness_id(), 8, '0');
		return "AL_" + bill.getBusiness_type() + "_" + LocalDateHelper.formatLongNoSplit(LocalDateTime.now()) + "_" + v;
	}

	@Override
	public String makeRequestString(PayBill bill) {
		// 设置请求参数
		AlipayRequest<?> alipayRequest = null;
		if ("alipay.trade.page.pay".equals(this.getPayMerchantChannel().getSmall_image())) {
			alipayRequest = new AlipayTradePagePayRequest();
		} else
			alipayRequest = new AlipayTradeWapPayRequest();
		// AlipayTradePagePayRequest
		alipayRequest.setReturnUrl(this.getPayMerchantChannel().getPage_url());
		alipayRequest.setNotifyUrl(this.getPayMerchantChannel().getNotice_url());

		// 商户订单号，商户网站订单系统中唯一订单号，必填
		String out_trade_no = this.makeBillNo(bill);
		// 付款金额，必填
		String total_amount = String.format("%.2f", ((double) (bill.getBill_amount())) / 100);
		// 订单名称，必填
		String subject = StringHelper.isEmpty(this.getPayMerchantChannel().getChannel_goods_name()) ? ""
				: this.getPayMerchantChannel().getChannel_goods_name();
		// 商品描述，可空
		AliPayOrderDetailRequest detail = new AliPayOrderDetailRequest();
		detail.setOut_trade_no(out_trade_no);
		detail.setTotal_amount(total_amount);
		detail.setSubject(subject);
		detail.setProduct_code("FAST_INSTANT_TRADE_PAY");
		// 自有参数
		detail.setPassback_params(bill.getBill_id() + "");
		// 超时时间
		if (StringHelper.isNotEmpty(this.getPayMerchantChannel().getMc_params()))
			detail.setTimeout_express(this.getPayMerchantChannel().getMc_params());
		if ("alipay.trade.page.pay".equals(this.getPayMerchantChannel().getSmall_image())) {
			((AlipayTradePagePayRequest) alipayRequest).setBizContent(JsonHelper.fromObject(detail));
		} else
			((AlipayTradeWapPayRequest) alipayRequest).setBizContent(JsonHelper.fromObject(detail));
		// System.out.println(alipayRequest.getBizContent());

		// 若想给BizContent增加其他可选请求参数，以增加自定义超时时间参数timeout_express来举例说明
		// alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
		// + "\"total_amount\":\""+ total_amount +"\","
		// + "\"subject\":\""+ subject +"\","
		// + "\"body\":\""+ body +"\","
		// + "\"timeout_express\":\"10m\","
		// + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
		// 请求参数可查阅【电脑网站支付的API文档-alipay.trade.page.pay-请求参数】章节

		// 请求
		String result = "";
		try {
			result = alipayClient.pageExecute(alipayRequest).getBody();
			return result;
		} catch (Exception e) {
			return null;
		}
	}

	@Override
	public PayBill processReply(PayBillDao daoBill, PayBill bill, HttpServletRequest request,
			Map<String, Object> paramMap) {
		// 验证签名
		// 获取支付宝POST过来反馈信息
		Map<String, String> params = getRequestMap(request);
		Map<String, String[]> requestParams = request.getParameterMap();
		for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
			String name = (String) iter.next();
			String[] values = (String[]) requestParams.get(name);
			String valueStr = "";
			for (int i = 0; i < values.length; i++) {
				valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
			}
			// // 乱码解决，这段代码在出现乱码时使用
			// try {
			// valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
			// } catch (Exception e) {
			//
			// }
			params.put(name, valueStr);
		}

		boolean signVerified = false;
		try {
			signVerified = AlipaySignature.rsaCheckV1(params, this.alipay_public_key, this.charset, this.sign_type); // 调用SDK验证签名
		} catch (Exception e) {
			LogHelper.error(e);
		}
		if (signVerified) {
			AliPayOrderNoticeResponse entity = (AliPayOrderNoticeResponse) paramMap.get("AliPayOrderNoticeResponse");
			if ("TRADE_SUCCESS".equals(entity.getTrade_status())) {
				LocalDateTime pay_time = LocalDateHelper.parseDateTime(entity.getGmt_payment());
				bill.setReply_time(LocalDateTime.now());
				bill.setBill_status(PayBillStatus.Complete);
				bill.setChannel_no(entity.getTrade_no());
				// 首次成交 更新订单
				try {
					int count = daoBill.completeBill(bill.getBill_id(), pay_time, bill.getReply_time(),
							entity.getTrade_no());
					if (count == 0)
						return bill;
					PayBillAlipay wx = BeanHelper.copy(PayBillAlipay.class, entity);
					wx.setBill_id(bill.getBill_id());
					try {
						daoBill.insert(wx);
					} catch (Exception e) {
						LogHelper.error(e);
					}
					return bill;
				} catch (Exception e) {
					this.logReply(bill, BillProcessResult.DatabaseError, "", request);
					return null;
				}
			}
		} else {
			// 验签失败
			this.logReply(bill, BillProcessResult.HamcError, "", request);
		}

		return bill;

	}

}
