java 对接支付宝支付
2019獨角獸企業重金招聘Python工程師標準>>>
對接支付寶支付的前提:
1,商戶開通支付能力
登錄螞蟻金服 開放平臺:https://open.alipay.com/platform/home.htm
需要開通 的功能選項有:
創建應用,類型是:網頁&移動應用
設置應用的RSA 等各項參數,界面如下:
支付寶推薦使用RSA2 加密方式,老版的加密方式只有RSA 和md5,沒有RSA2.
本項目使用RSA2 加密方式
2,對接支付寶依賴的jar包
<!-- https://mvnrepository.com/artifact/net.guerlab/sdk-alipay-core --><dependency><groupId>net.guerlab</groupId><artifactId>sdk-alipay-core</artifactId><version>1.0.3</version></dependency>?
我寫了一個專門封裝對接支付寶的Service 層
見代碼:https://gitee.com/kunlunsoft/pay_service.git
項目結構:
發起支付 控制器(需根據實際情況修改):
下面的"/order/startPay"接口
package com.girltest.web.controller.pay;import com.common.annotation.NoLogin; import com.common.bean.BaseResponseDto; import com.common.dict.Constant2; import com.common.util.RedisHelper; import com.common.util.SystemHWUtil; import com.girltest.dao.AlipayNotifySuccessDao; import com.girltest.dao.BusinessOrderDao; import com.girltest.entity.BusinessOrder; import com.house.ujiayigou.thirdpart.alipay.config.AlipayConfig; import com.house.ujiayigou.thirdpart.alipay.info.PayFormInfo; import com.string.widget.util.RandomUtils; import com.string.widget.util.ValueWidget; import com.time.util.TimeHWUtil; import com.yunmasoft.service.pay.AlipayNotifySuccessService; import com.yunmasoft.service.pay.alipay.AliPayService; import com.yunmasoft.service.pay.alipay.PayOperation; import com.yunmasoft.service.pay.alipay.PayService; import oa.entity.AlipayNotifySuccess; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody;import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.math.BigDecimal; import java.util.Date;/*** Created by tonyjiang on 15/8/28.*/@Controller public class PayOrderController {@Resource(name = "alipay")private AliPayService aliPayService;public static org.slf4j.Logger HttpClientRestLogger = LoggerFactory.getLogger("pay_log");// @Resource // private OrderDetailViewModel orderDetailViewModel;@Resourceprivate AlipayNotifySuccessDao alipayNotifySuccessDao;@Resourceprivate AlipayNotifySuccessService alipayNotifySuccessService;@Resourceprivate BusinessOrderDao businessOrderDao;/**** 抹掉小數點后面的零頭** @param orderPrice* @return*/private static String removeDecimalPoint(BigDecimal orderPrice) {String formatPrice = ValueWidget.formatBigDecimal(orderPrice);return formatPrice;}private static void checkOrderStatus(int orderStatus) {if (orderStatus == Constant2.ORDERSTATUS_PAID_ALREADY) {//支付完成,調到支付成功頁 // LogicBusinessException.throwException("alreadyPaid");} else if (orderStatus == Constant2.ORDERSTATUS_CANCELLED) {//已經取消了訂單 // LogicBusinessException.throwException("alreadyCancel");}}/**** 通過redis 獲取訂單的支付結果:是否支付成功* @param request* @param response* @param httpSession* @param model* @param orderNo* @return*/@RequestMapping("/order/payOrderResult")@ResponseBodypublic String getOrderPayResult(HttpServletRequest request, HttpServletResponse response, HttpSession httpSession, Model model,@RequestParam(value = "orderNo", required = true) String orderNo) {BaseResponseDto baseResponseDto = new BaseResponseDto(PayService.isPaySuccess(orderNo));return baseResponseDto.toJson();}/**** 下單頁* @param model* @param request* @param response* @param release* @return*/@RequestMapping(value = "/order/place", produces = SystemHWUtil.RESPONSE_CONTENTTYPE_JSON_UTF)public String json2(Model model, HttpServletRequest request, HttpServletResponse response, @RequestParam(required = false, defaultValue = "true") Boolean release) {String orderNo = "Xr20001" + RandomUtils.getNextInt();model.addAttribute("orderNo", orderNo);return "pay/wap/placeorder";}/**** 步驟:* 1,獲取當前用戶信息* 2,根據訂單號查詢訂單詳情* 3,校驗訂單狀態和支付方式* 4,跳轉到第三方支付* @param request* @param response* @param httpSession* @param model* @param orderNo* @param callback* @return* @throws Exception*/@RequestMapping("/order/startPay")@NoLoginpublic String startPay(HttpServletRequest request, HttpServletResponse response, HttpSession httpSession, Model model,@RequestParam(value = "orderNo", required = true) String orderNo,@RequestParam(value = "callback", required = false) String callback, BigDecimal shouldPay) throws Exception {//p判斷該訂單號是否已經存在AlipayNotifySuccess alipayNotifySuccess = this.alipayNotifySuccessService.getAlipayNotifySuccess(orderNo);if (null != alipayNotifySuccess) {model.addAttribute("errorMessage", "該訂單號已經存在,orderNo:" + orderNo);return "pay/alipay";}// 判斷訂單號是否存在BusinessOrder businessOrder = this.businessOrderDao.get("orderNo", orderNo);if (null == businessOrder) {model.addAttribute("errorMessage", "該訂單號不存在,orderNo:" + orderNo);return "pay/alipay";} /*//保存訂單businessOrder = new BusinessOrder();businessOrder.setOrderNo(orderNo);businessOrder.setTotalPrice(shouldPay);CreateTimeUtil.fillTime(businessOrder);this.businessOrderDao.add(businessOrder);*///獲取當前用戶信息//7.應付金額String strShouldPay = null;if (ValueWidget.isNullOrEmpty(shouldPay)) {shouldPay=businessOrder.getPrice();}strShouldPay = ValueWidget.formatBigDecimal(shouldPay);//8. 賬戶String sellerAccount = AlipayConfig.seller_email;//9.其它 // RedisHelper.getInstance().saveKeyCache(PayService.REDIS_KEY_STORE_ORDER_PAY_TIME, orderNo, TimeHWUtil.formatDate(new Date(), TimeHWUtil.YYYYMMDD_NO_LINE));String orderName = businessOrder.getProductBaseInfo().getDisplayName();//10.com.house.ujiayigou.thirdpart.alipay.info.PayFormInfo payFormInfo = new PayFormInfo();payFormInfo.setOut_trade_no(orderNo);payFormInfo.setSubject(orderName);payFormInfo.setBody(orderName);payFormInfo.setTotal_amount(strShouldPay);payFormInfo.setSeller_id(sellerAccount);String form = aliPayService.preparePostRequest(payFormInfo);HttpClientRestLogger.error("form:" + form);model.addAttribute("form", form);return "pay/alipay";}/*** 1,獲取訂單;* 2,價格;* 3,Identify;* 4,第三方支付相關接口service;* 5,callback* 6,coupon* 7,應付金額* 8,賬戶* 9,其它* 10,** @param access_token* @param orderNo* @param payType* @param callback* @return*/public String postThirdPayAction(String access_token, String orderNo, String payType, String callback) {//訂單/* OrderInfoBean orderInfo = orderBusiness.getOrderInfoByOrderNo(access_token, orderNo);if (orderInfo == null || orderInfo.getItems().size()==0) {LogicBusinessException.throwException("cannotMatchOrder");}checkOrderStatus(orderInfo.orderStatus);if (orderInfo.orderStatus != Constant.ORDERSTATUS_ORDERS_SUBMITTED) {LogicBusinessException.throwException("20506");}*///2.價格BigDecimal price = null;//orderBusiness.getOrderMoney(orderInfo);if (price == null) { // LogicBusinessException.throwException("cannotPay");}//3.IdentifyString identifier = null;//orderBusiness.getPayIdentify(orderNo, access_token, userInfo, price);PayOperation service = null;//(PayOperation) SpringMVCUtil.getBean( payType);if (service == null) { // LogicBusinessException.throwException("service is null");}//5.callbackif (ValueWidget.isNullOrEmpty(callback)) {callback = "https:/order/view?orderNo=" + orderNo /*+ "&orgId=" + orgId*/;//千萬不要URL轉碼}//6.couponBigDecimal coupon = null;/*if (Constant.useDebugCouponValue) {coupon = new BigDecimal(Constant.couponValue);} else {*/coupon = new BigDecimal(0); // }//7.應付金額BigDecimal shouldPay = price.subtract(coupon.compareTo(price) < 0 ? coupon : new BigDecimal(0));//String strShouldPay = ValueWidget.formatBigDecimal(shouldPay);//8. 賬戶String sellerAccount = AlipayConfig.seller_email;//9.其它RedisHelper.getInstance().saveKeyCache(PayService.REDIS_KEY_STORE_ORDER_PAY_TIME, orderNo, TimeHWUtil.formatDate(new Date(), TimeHWUtil.YYYYMMDD_NO_LINE));String orderName = "xxx服務";//10.com.house.ujiayigou.thirdpart.alipay.info.PayFormInfo payFormInfo = new PayFormInfo();payFormInfo.setOut_trade_no(orderNo);payFormInfo.setSubject(orderName);payFormInfo.setBody(orderName);payFormInfo.setTotal_amount(strShouldPay);payFormInfo.setSeller_id(sellerAccount);String form = service.preparePostRequest(payFormInfo);return form;}}支付回調控制器(需根據實際情況修改):
下面的"/notify"接口
package com.girltest.web.controller.pay;import com.common.dict.Constant2; import com.common.util.*; import com.yunmasoft.service.pay.alipay.PayOperation; import com.io.hw.json.HWJacksonUtils; import com.string.widget.util.ValueWidget; import oa.util.SpringMVCUtil; import org.apache.log4j.Logger; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody;import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Map;@Controller @RequestMapping("/pay") public class PayController {public static Logger logger = Logger.getRootLogger();@RequestMapping(value = "notify", produces = {SystemHWUtil.RESPONSE_CONTENTTYPE_JSON_UTF})@ResponseBodypublic String callback(@RequestParam(required = false) String method,@RequestParam(required = false) String out_trade_no/*訂單號*/,@RequestParam(required = false) String trade_no,@RequestParam(required = false) String trade_status,@RequestParam(required = false) String extra_common_param,@RequestParam(required = false) String notifyUrl,@RequestParam(required = false) String body/*只有支付寶手機網站支付才有*/,HttpServletResponse response,HttpServletRequest request) {//userIdAndLoginnameAndOrgId 在請求參數中// 1.獲取訂單號if (ValueWidget.isNullOrEmpty(out_trade_no)) {out_trade_no = request.getParameter("outer_trade_no");}// 2.暢捷支付沒有extra_common_param,兼容暢捷支付if (ValueWidget.isNullOrEmpty(extra_common_param) && !ValueWidget.isNullOrEmpty(notifyUrl)) {//added by huangweiiMap argMap = RequestUtil.parseQueryString(notifyUrl);extra_common_param = (String) argMap.get("chanpay");}logger.info(HWJacksonUtils.getJsonP(request.getParameterMap()));// 3.兼容extra_common_param為空的情況boolean isAlipayMobile = false;if (ValueWidget.isNullOrEmpty(extra_common_param)) {//added by huangweii,extra_common_param為空,說明是xx支付String extra_common_paramSuffix = RedisHelper.getInstance().getCache("store_" + out_trade_no + "_Identifier") +"::" + RedisHelper.getInstance().getCache("store_" + out_trade_no + "_userinfo");if (ValueWidget.isNullOrEmpty(request.getParameter("out_trade_no"))) {extra_common_param = "chanpay::" + extra_common_paramSuffix;} else {isAlipayMobile = true;extra_common_param = "alipay::" + extra_common_paramSuffix;}}// 4. 緩存日志 // String currentCache = RedisHelper.getInstance().getKeyCache(Constant.REDIS_ID_STORE, out_trade_no) + "<br>"; // RedisHelper.getInstance().saveKeyCacheAndExpire(Constant.REDIS_ID_STORE, out_trade_no, currentCache +request.getRequestURI()+ extra_common_param + ",notifyUrl:" + notifyUrl);logger.info("extra_common_param:" + extra_common_param);// 獲取支付寶POST過來反饋信息Map requestParams = request.getParameterMap();Map<String, String> params = WebServletUtil.getParamMap(requestParams); // params.put("userIdAndLoginnameAndOrgId", userIdAndLoginnameAndOrgId);// 5.獲取servicePayOperation service = null;if (extra_common_param != null && extra_common_param.contains("::")) {String[] info = extra_common_param.split("::");service = (PayOperation) SpringMVCUtil.getBean(request, info[0]);}if (service == null) {return "fail";}// 6.驗簽String verity_ok = service.verify(WebServletUtil.getParamMap(requestParams));if (!verity_ok.equals("success")) {logger.error(params.toString());logger.error("verify fail");return verity_ok;}// 7. 緩存日志 // currentCache = RedisHelper.getInstance().getKeyCache(Constant.REDIS_ID_STORE, out_trade_no) + "<br>"; // RedisHelper.getInstance().saveKeyCacheAndExpire(Constant.REDIS_ID_STORE, out_trade_no, currentCache + "verity->" + verity_ok);// 8.回調,調用確認訂單接口try {String pay_ok = service.payNotify(out_trade_no, trade_no, trade_status, params);if (pay_ok != null) {logger.debug(pay_ok + "");return pay_ok; // 請不要修改或刪除}} catch (Exception ex) {logger.error("payNOtify error:", ex);return "fail";}return "fail";}@RequestMapping(value = "payResult")public String getPaymentResult(@RequestParam(required = false) String orderid,@RequestParam(required = false) String userid,HttpServletRequest request,HttpServletResponse response,Model model) throws IOException {logger.info("payResult orderid:" + orderid);// 獲取支付寶POST過來反饋信息Map requestParams = request.getParameterMap();Map<String, String> params = WebServletUtil.getParamMap(requestParams);String orderId = orderid;if (ValueWidget.isNullOrEmpty(orderId)) {orderId = params.get("orderid");}if (orderId == null) {orderId = params.get("out_trade_no");}//暢捷支付點擊[返回商家] TODOif (orderId == null) {orderId = params.get("orderId");}logger.info("payResult params:" + params);String payResult = params.get("payResult");String extra_common_param = params.get("extra_common_param");logger.info("payResult extra_common_param:" + extra_common_param);if (!Constant2.CHANPAY_ORDER_RESULT_SUCCESS.equals(payResult)) {response.sendRedirect("/order/payOrder?orderId=" + orderId /*+ "&orgId=" + service.getOrgId(orderId)*/);return null;}response.sendRedirect("/order/payComplete?orderId=" + orderId /*+ "&orgId=" + service.getOrgId(orderId)*/);return null;}}?
實際支付demo:
http://i.yhskyc.com/product/1
各文檔:
電腦網站支付快速接入
https://docs.open.alipay.com/270/105899/
API 詳細說明:
https://docs.open.alipay.com/270/alipay.trade.page.pay/
服務端SDK
https://docs.open.alipay.com/54/103419
RSA私鑰及公鑰生成
https://docs.open.alipay.com/58/103242/
?
RSA私鑰及公鑰生成 工具:
https://gitee.com/kunlunsoft/http_request_tool
上圖中2048 對應RSA2
相關項目:
https://github.com/liuyu520/io0007
https://gitee.com/kunlunsoft/oa_framework
注意:
1,本項目使用新版支付寶支付
即時到賬新老版本接口對比
https://docs.open.alipay.com/270/106759
2,新版支付寶支付,就算僅使用PC端網頁支付,也需要創建一個應用,老版不需要.
3,電腦端網頁支付應該使用:
AlipayTradePagePayRequest,而不是AlipayTradePayRequest;
4,對業務參數(非公共參數),進行 json 序列化時,
一定使用阿里自己的類:
JSONWriter?writer = new JSONWriter();
String body=writer.write(model, true);
轉載于:https://my.oschina.net/huangweiindex/blog/1637847
總結
以上是生活随笔為你收集整理的java 对接支付宝支付的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2018最新大神教你用Python玩转数
- 下一篇: Tomcat启动过程源码解读