1. 程式人生 > >支付寶線下門店掃碼支付開發

支付寶線下門店掃碼支付開發

支付寶掃碼支付

一.開發前準備

https://doc.open.alipay.com/doc2/detail.htm?spm=0.0.0.0.B6xA20&treeId=26&articleId=103239&docType=1

1.開通支付寶企業號

2.簽約認證

3.建立應用,稽核通過。

4.上傳應用公鑰。

二.開發demo從支付寶官網下載

alipay-sdk-Java-ALL20150604113758-source.jar

alipay-sdk-java-ALL20150604113758.jar

/**
	 * 呼叫支付寶掃碼支付二維碼生成
	 * 
	 * @return
	 */
	public String aliQr() {
		String orderId = httpServletRequest.getParameter("orderId");
		String out_trade_no = getTradeNo();
		String total_amount = httpServletRequest.getParameter("total_amount");
		String subject = "";
		String companyId = getCompanyInfo().getCompanyId();
		Order o = null;
		try {
			o = orderService.getOrderById(Integer.parseInt(orderId));
			subject = CommonCompanyName(o.getCompanyId(), o.getSubCompanyId())
					+ "的商品" + total_amount + "元";
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		AlipayTradePrecreateResponse response = qrPay(out_trade_no,
				total_amount, subject, companyId, orderId, o.getSubCompanyId());
		if (null != response && response.isSuccess()) {
			ResponseWriteUtil.writeHTML("{\"code\":\"" + response.getQrCode()
					+ "\"," + "\"outTradeNo\":\"" + response.getOutTradeNo()
					+ "\"}");
			// 生成自定義二維碼圖片
			// String path = "/qrcode/" + companyId + "/" + out_trade_no +
			// ".png";
			// String qrCodePath = ServletActionContext.getServletContext()
			// .getRealPath(path);
			// ZXingQrCode.createQrCodeImg(300, 300, response.getQrCode(),
			// qrCodePath);
			// 儲存二維碼值
			HashMap<String, Object> map = new HashMap<String, Object>();
			map.put("orderId", orderId);
			map.put("aliqrcodeUrl", response.getQrCode());
			// map.put("aliqrcodeUrl", ConfigUtil.SYS_BASE_URL + path);
			orderService.updateAliQrCodeByOrderId(map);
		} else {
			ResponseWriteUtil.writeHTML("{\"code\":\"0\"}");// 不存在
		}
		return null;
	}

	public String CommonCompanyName(String companyId, String subCompanyId) {
		Seller seller = sellerService.findSellerByCompanyId(companyId);
		String commonMsg = "";
		SubCompany subCompany = null;
		if (StringUtils.isNotBlank(subCompanyId)) {
			subCompany = subCompanyService.fetchSubCompanyBySid(subCompanyId);
		}
		if (subCompany == null) {// 主店
			commonMsg = seller.getCompanyName();
		} else {// 分店
			commonMsg = subCompany.getCompanyShortName();
		}
		return commonMsg;
	}

	/**
	 * 是否配置了支付寶二維碼支付
	 * 
	 * @return
	 */
	public String isExistByAliPayQrCode() {
		String companyId = httpServletRequest.getParameter("companyId");
		String subCompanyId = httpServletRequest.getParameter("subCompanyId");
		HashMap<String, Object> map2 = new HashMap<String, Object>();
		map2.put("companyId", companyId);
		map2.put("subCompanyId", subCompanyId);
		ALIPayConfigure aliPayConfigure = aliPayConfigureService
				.selectAppId(map2);
		if (aliPayConfigure != null) {
			ResponseWriteUtil.writeHTML("{\"code\":\"" + 1 + "\"}");
		} else {
			ResponseWriteUtil.writeHTML("{\"code\":\"" + 0 + "\"}");
		}
		return null;
	}

/**
	 * 回撥通知處理
	 * 
	 * @return
	 */
	public String notifyMsgByAliPay() {
		String orderId = httpServletRequest.getParameter("orderId");
		String totalAmount = httpServletRequest.getParameter("totalAmount");
		String outTradeNo = httpServletRequest.getParameter("outTradeNo");
		System.out.println("訂單號:" + orderId + ",訂單金額:" + totalAmount
				+ ",商戶交易號:" + outTradeNo);
		System.out.println("支付寶非同步回撥通知:");
		// 判斷付款是否成功,已成功則不再記錄付款資訊
		if (orderService.ifOrderPaid(Integer.parseInt(orderId)) > 0) {
			log.info("付款已成功,不再記錄付款資訊");
			ResponseWriteUtil.writeHTML("success");
			return null;
		}
		aliPayService.aliPayFinsh(Integer.parseInt(orderId), totalAmount,
				outTradeNo);
		System.out.println("系統訂單業務處理完成");
		ResponseWriteUtil.writeHTML("success");// 告訴支付寶我已處理,不需要重複發非同步通知
		System.out.println("支付寶非同步回撥通知成功結束");
		return null;
	}

js頁面

//*************start*********aliPayByQr******************************
//是否配置了支付寶掃碼
function isExistByAliPayQrCode(){
	var companyId=$("#companyId").val();
	var subCompanyId=$("#subCompanyId").val();
	if(subCompanyId==null||subCompanyId=='null'||subCompanyId==undefined){
		subCompanyId="";
	}
	$.ajax({
		url : '<%=basePath%>/aliPay!isExistByAliPayQrCode.action?companyId='+companyId+'&subCompanyId='+subCompanyId,
		async : false,
		type : "post",
		dataType : "json",
		success : function(result) {
			 if(result.code!='0'){
			 	$("#aliQrBtn").show();
			 }else{
			 	$("#aliQrBtn").hide();
			 	layer.msg("商家沒有配置支付寶掃碼支付!");
			 }
		}
	});
}
	
function aliQrClick(){
	var total_amount=$("#paymentAmount").val();
	var orderId=$("#myorderId").val();
	//check
	var paySize=$(".payMoneyC").length;
	var ptypeNum=$(".ptype:checked").length;
	var paySum=0;
	if(ptypeNum<=0){
		layer.msg("支付方式至少選擇一個!");
		return;
	}
	if(ptypeNum!=1){
		layer.msg("支付方式只能是支付寶掃碼支付!");
		return;
	}
	var companyId=$("#companyId").val();
	var subCompanyId=$("#subCompanyId").val();
	if(subCompanyId==null||subCompanyId=='null'||subCompanyId==undefined){
		subCompanyId="";
	}
	$.ajax({
		url : '<%=basePath%>/aliPay!aliQr.action',
		async : false,
		type : "post",
		dataType : "json",
		data:{"total_amount":total_amount,"orderId":orderId},
		success : function(result) {
			if(result.code!='0'){
				$("#aliQrBtn").hide();
				$("#outputALIQr").show();
				<span style="color:#ff0000;">jQuery('#outputALIQr').qrcode({width:200,height:200,text:result.code});//</span><span style="color: rgb(255, 0, 0); font-family: Arial, Helvetica, sans-serif;">js</span><span style="color: rgb(255, 0, 0); font-family: Arial, Helvetica, sans-serif;">二維碼生成</span><span style="color:#ff0000;">
</span>				window.setInterval(finshAliQrPay, 8000); 
			}else{
				layer.msg("支付寶二維碼生成出錯!");
			}
		}
	});
}

function qrQueryRetry(out_trade_no){
	$.ajax({
		url : '<%=basePath%>/aliPay!aliQueryRetry.action',
		async : false,
		type : "post",
		dataType : "json",
		data:{"out_trade_no":out_trade_no},
		success : function(result) {
		}
	});
}
var aliNum=0;
function finshAliQrPay(){
 	var orderId=$("#myorderId").val();
	$.ajax({
		url : '<%=basePath%>/aliPay!<span style="color:#cc0000;background-color: rgb(255, 255, 255);">notifyOrderCashFinshed</span>.action?orderId='+orderId,
		async : false,
		type : "post",
		dataType : "json",
		data:$('#finishForm').serialize(),
		success : function(result) {
			 if(result.code!='0'){
			 	layer.msg("支付寶掃碼支付交易成功,訂單3秒後即將關閉!");
			 	window.setTimeout(function(){
			 	//關閉彈出窗之前,跳轉到其他頁面
			    parent.window.location.href="<%=path%>/"+result.redirectUrl;
			    closeLayerDialog();
			 	},3000); 
			 }else{
			    aliNum=aliNum+1;
			 	$("#aliQrPayNotifyNum").val(aliNum);
			 }
		}
	});
}

//*************end*******aliPayByQr********************************

5.aliPayService 實現類
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;


@Service("aliPayService")
public class ALIPayServiceImpl implements ALIPayService {
	Logger log = Logger.getLogger(ALIPayServiceImpl.class);

	@Resource
	private OrderDAO orderDAO;
	@Resource
	private SerialNumMngDAO serialNumMngDAO;
	@Resource
	private ALIPayTradeLogsDAO aliPayTradeLogsDAO;
	@Resource
	private ALIPayConfigureDAO aliPayConfigureDAO;

	@Resource
	private ALIPayTradeLogsService aliPayTradeLogsService;
	@Resource
	private ALIPayConfigureService aliPayConfigureService;
	@Resource
	private OrderService orderService;

	@Override
	public void aliPayFinsh(Integer orderId, String totalAmount,
			String outTradeNo) {
		// TODO Auto-generated method stub
		Order o = null;
		float paymentAmount = Float.parseFloat(totalAmount);
		try {
			o = orderDAO.getOrderbyId(orderId);
			// 系統交易流水記錄
			List<OrderPlus> ops = new ArrayList<OrderPlus>();
			OrderPlus op = new OrderPlus();
			op.setOrderId(o.getId());
			op.setOrderAmount(o.getAmount());
			op.setPaymentAmount(paymentAmount);
			op.setPaymentTime(new Date());
			op.setPaymentType(EnumUtil.PAYMENT_TYPE.alipayqrbycompay.getCode());
			op.setNotes("支付寶掃碼支付:支付金額為" + paymentAmount);
			ops.add(op);
			orderDAO.insertOrderPlusPitch(ops);

			// 更新系統訂單業務
			HashMap<String, Object> map = new HashMap<String, Object>();
			map.put("orderId", o.getId());
			// 外賣
			if (o.getIsTakeOut() == 1) {
				map.put("dealSts", EnumUtil.ORDER_dealSts.finished.getCode());
			} else {
				map.put("dealSts", EnumUtil.ORDER_dealSts.paid.getCode());
			}
			map.put("finishTime", new Date());
			map.put("paymentAmount", paymentAmount);
			map.put("orderPersonNum", 0);
			map.put("orderTime", o.getOrderTime());
			serialNumMngDAO.finishOrder(map);

			// 支付寶交易流水記錄
			HashMap<String, Object> map2 = new HashMap<String, Object>();
			map2.put("companyId", o.getCompanyId());
			map2.put("subCompanyId", o.getSubCompanyId());
			ALIPayConfigure alipc = aliPayConfigureDAO.selectAppId(map2);
			ALIPayTradeLogs aliPaytl = new ALIPayTradeLogs();
			aliPaytl.setOutTradeNo(outTradeNo);
			if (alipc != null) {
				aliPaytl.setAppId(alipc.getAppId());
			}
			aliPaytl.setOrderId(String.valueOf(orderId));
			aliPaytl.setTotalAmount(paymentAmount);
			aliPaytl.setChannel("ALI_OFFLINE_QRCODE");
			aliPaytl.setTradeDate(new Date());
			aliPayTradeLogsDAO.insert(aliPaytl);

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public HashMap<String, Object> refundOrderByALIQr(String orderId,
			String refund_amount) {
		// TODO Auto-generated method stub
		HashMap<String, Object> map = new HashMap<String, Object>();
		ALIPayTradeLogs ali = aliPayTradeLogsService.selectByOrderId(Integer
				.parseInt(orderId));
		if (ali != null) {
			Order o = null;
			try {
				o = orderService.getOrderById(Integer.parseInt(orderId));
			} catch (Exception e) {
				e.printStackTrace();
			}
			HashMap<String, Object> queryMap = query(ali.getOutTradeNo(),
					o.getCompanyId(), o.getSubCompanyId());
			int flag = (Integer) queryMap.get("flag");
			String tradeNo = (String) queryMap.get("tradeNo");
			if (flag == 1) {
				boolean refundFlag = refundOrder(tradeNo, refund_amount, "",
						o.getCompanyId(), o.getSubCompanyId());
				map.put("refundFlag", refundFlag);
				map.put("refundMsg", "支付寶掃碼(企業)提示:該支付款按原路退到買家帳號,請注意查收!");
			} else if (flag == 2) {
				map.put("refundFlag", false);
				map.put("refundMsg", "平臺提示:支付寶掃碼等待付款");
			} else if (flag == 3) {
				map.put("refundFlag", false);
				map.put("refundMsg", "平臺提示:支付寶掃碼未付款關閉,或已付款的訂單全額退款後關閉");
			} else if (flag == 4) {
				map.put("refundFlag", false);
				map.put("refundMsg", "平臺提示:支付寶掃碼訂單不可退款或撤銷");
			} else if (flag == 0) {
				map.put("refundFlag", false);
				map.put("refundMsg", "平臺提示:支付寶掃碼請求未成功,請重試");
			}
		}
		return map;
	}

	public HashMap<String, Object> query(final String out_trade_no,
			String companyId, String subCompanyId) {
		String tradeNo = "";
		HashMap<String, Object> map = new HashMap<String, Object>();
		AlipayClient alipayClient = getAlipayClientByCompanyId(companyId,
				subCompanyId);
		AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
		String biz_content = "{\"out_trade_no\":\"" + out_trade_no + "\"}";
		request.setBizContent(biz_content);
		AlipayTradeQueryResponse response = null;
		try {
			response = alipayClient.execute(request);
			System.out.println(response.getBody());
			System.out.println(response.getCode());
			if (null != response && response.isSuccess()) {
				System.out.println("買家賬號:" + response.getBuyerLogonId());
				System.out.println("商戶訂單號:" + response.getOutTradeNo());
				System.out.println("支付寶交易號:" + response.getTradeNo());
				System.out.println("總金額:" + response.getTotalAmount());
				System.out.println("訂單狀態:" + response.getTradeStatus());
				if (response.getCode().equals("10000")) {
					tradeNo = response.getTradeNo();
					if ("TRADE_SUCCESS".equalsIgnoreCase(response
							.getTradeStatus())) {
						map.put("tradeNo", tradeNo);
						map.put("flag", 1);
						// 表示已付款
					} else if ("WAIT_BUYER_PAY".equalsIgnoreCase(response
							.getTradeStatus())) {
						map.put("tradeNo", tradeNo);
						map.put("flag", 2);
						// 表示等待付款
					} else if ("TRADE_CLOSED".equalsIgnoreCase(response
							.getTradeStatus())) {
						map.put("tradeNo", tradeNo);
						map.put("flag", 3);
						// 表示未付款關閉,或已付款的訂單全額退款後關閉
					} else if ("TRADE_FINISHED".equalsIgnoreCase(response
							.getTradeStatus())) {
						// 此狀態,訂單不可退款或撤銷
						map.put("tradeNo", tradeNo);
						map.put("flag", 4);
					}
				} else {
					// 如果請求未成功,請重試
					map.put("tradeNo", tradeNo);
					map.put("flag", 0);
				}
			}
		} catch (AlipayApiException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return map;
	}

	/**
	 * 申請退單
	 * 
	 * @param trade_no
	 * @author jinlong.rhj
	 * @date 2015年4月27日
	 * @version 1.0
	 * @return
	 */
	public boolean refundOrder(String trade_no, String refund_amount,
			String out_request_no, String companyId, String subCompanyId) {
		boolean flag = false;
		AlipayClient alipayClient = getAlipayClientByCompanyId(companyId,
				subCompanyId);
		AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();

		String biz_content = "{\"trade_no\":\""
				+ trade_no
				+ "\",\"refund_amount\":\""
				+ refund_amount
				+ "\",\"out_request_no\":\""
				+ out_request_no
				+ "\",\"refund_reason\":\"正常退單\",\"store_id\":\"\",\"terminal_id\":\"\"}";
		System.out.println(biz_content);
		request.setBizContent(biz_content);

		AlipayTradeRefundResponse response = null;

		try {
			response = alipayClient.execute(request);
			// System.out.println(response.getBody());
			// System.out.println(response.getCode());
			// System.out.println(response.getMsg());
			// System.out.println(response.getSubCode());
			// System.out.println(response.getSubMsg());
			// System.out.println(response.getBuyerLogonId());
			// System.out.println(response.getFundChange());
			// System.out.println(response.getOpenId());
			// System.out.println(response.getOutTradeNo());
			// System.out.println(response.getRefundFee());
			// System.out.println(response.getGmtRefundPay());
			// System.out.println(response.getOpenId());
			if (null != response && response.isSuccess()) {
				if (response.getCode().equals("10000")) {
					if (response.getFundChange().equals("Y")) {
						// 退款成功,資金有變動,做業務及賬務處理
						flag = true;
					} else {
						// 資金無變動,不必做賬務處理
					}
				} else {
					// 沒有撤銷成功,需要重試幾次
					// refundOrderRetry(trade_no, refund_amount, out_request_no,
					// 6);
				}
			}
		} catch (AlipayApiException e) {
			e.printStackTrace();
		}
		return flag;
	}

	@Override
	public AlipayClient getAlipayClientByCompanyId(String companyId,
			String subCompanyId) {
		HashMap<String, Object> map2 = new HashMap<String, Object>();
		map2.put("companyId", companyId);
		map2.put("subCompanyId", subCompanyId);
		ALIPayConfigure aliPayConfigure = aliPayConfigureService
				.selectAppId(map2);
		DefaultAlipayClient alipayClient = null;
		if (aliPayConfigure != null) {
			alipayClient = new DefaultAlipayClient(
					AlipayServiceEnvConstants.ALIPAY_GATEWAY,
					aliPayConfigure.getAppId(),
					aliPayConfigure.getPrivateKey(), "json",
					AlipayServiceEnvConstants.CHARSET,
					AlipayServiceEnvConstants.ALIPAY_PUBLIC_KEY);
		}
		return alipayClient;
	}

	/**
	 * 支付寶掃碼支付二維碼生成介面
	 * 
	 * @param out_trade_no
	 * @param total_amount
	 * @param subject
	 * @param companyId
	 * @return
	 */
	public AlipayTradePrecreateResponse qrPay(String out_trade_no,
			String total_amount, String subject, String companyId,
			String orderId, String subCompanyId) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String time_expire = sdf.format(System.currentTimeMillis() + 24 * 60
				* 60 * 1000);
		StringBuilder sb = new StringBuilder();
		sb.append("{\"out_trade_no\":\"" + out_trade_no + "\",");
		sb.append("\"total_amount\":\"" + total_amount
				+ "\",\"discountable_amount\":\"0.00\",");
		sb.append("\"subject\":\"" + subject + "\",");
		sb.append("\"time_expire\":\"" + time_expire + "\"}");
		System.out.println(sb.toString());

		AlipayClient alipayClient = getAlipayClientByCompanyId(companyId,
				subCompanyId);

		// 使用SDK,構建群發請求模型
		AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
		request.setBizContent(sb.toString());
		request.setNotifyUrl(ConfigUtil.SYS_BASE_URL
				+ "/aliPay!notifyMsgByAliPay.action" + "?orderId=" + orderId
				+ "&totalAmount=" + total_amount + "&outTradeNo="
				+ out_trade_no);
		AlipayTradePrecreateResponse response = null;
		// 商家配置不成功
		if (alipayClient == null) {
			return response;
		}
		try {
			// 使用SDK,呼叫交易下單介面
			response = alipayClient.execute(request);

			System.out.println(response.getBody());
			System.out.println(response.isSuccess());
			System.out.println(response.getMsg());
			// 這裡只是簡單的列印,請開發者根據實際情況自行進行處理
			if (null != response && response.isSuccess()) {
				if (response.getCode().equals("10000")) {
					System.out.println("商戶訂單號:" + response.getOutTradeNo());
					System.out.println("二維碼值:" + response.getQrCode());// 商戶將此二維碼值生成二維碼,然後展示給使用者,使用者用支付寶手機錢包掃碼完成支付
					// 二維碼的生成,網上有許多開源方法,可以參看:http://blog.csdn.net/feiyu84/article/details/9089497

				} else {
					// 列印錯誤碼
					System.out.println("錯誤碼:" + response.getSubCode());
					System.out.println("錯誤描述:" + response.getSubMsg());
				}
			}
		} catch (AlipayApiException e) {
		}
		return response;
	}

}


ALIPayService介面
import java.util.HashMap;

import com.alipay.api.AlipayClient;
import com.alipay.api.response.AlipayTradePrecreateResponse;

public interface ALIPayService {

	/**
	 * 支付寶掃碼支付成功後,訂單業務處理
	 * 
	 * @param orderId
	 */
	public void aliPayFinsh(Integer orderId, String totalAmount,
			String outTradeNo);

	/**
	 * 支付寶掃碼支付申請退款業務處理
	 * 
	 * @param orderId
	 * @param refund_amount
	 * @return
	 */
	public HashMap<String, Object> refundOrderByALIQr(String orderId, String refund_amount);

	/**
	 * 各商家的獲得API呼叫客戶端
	 * 
	 * @param companyId
	 * @param subCompanyId
	 * @return
	 */
	public AlipayClient getAlipayClientByCompanyId(String companyId,
			String subCompanyId);

	/**
	 * 支付寶掃碼支付二維碼生成介面
	 * 
	 * @param out_trade_no
	 * @param total_amount
	 * @param subject
	 * @param companyId
	 * @return
	 */
	public AlipayTradePrecreateResponse qrPay(String out_trade_no,
			String total_amount, String subject, String companyId,
			String orderId, String subCompanyId);

}