天天看點

整合支付寶支付與退款以及回調

  1. 支付寶參數

    @Data
    @Component
    @ConfigurationProperties(prefix = "alipay")
    public class AliPayProperties {
    	
    	private String AppId;
    	//商戶私鑰
    	private String PrivateKey;
    	//支付寶公鑰
    	private String AliPayPublicKey;
    	//異步通知位址
    	private String NotifyUrl;
    	//回調位址
    	private String ReturnUrl;
    	//網關
    	private String URL="https://openapi.alipay.com/gateway.do";
    	
    	/**
    	 * 密鑰分為:公鑰和密鑰
    	 * 商戶應用公鑰簽名:以在支付寶背景配置了:來源:生成密鑰工具
    	 * 商戶應用私鑰簽名:java應用需要==代碼中需要配置:作用是商戶支付簽名:來源:生成密鑰工具
    	 * 
    	 * 支付寶公鑰簽名:java應用需要==代碼中需要配置:作用商戶異步資訊驗證簽名:支付寶背景配置商戶的公鑰之後會生成支付寶公鑰
    	 * 支付寶私鑰簽名:(我們看不到)
    	 * RSA對稱加密
    	 * 商戶發起支付向支付寶伺服器:商戶發起支付(用商戶應用私鑰加密)--->支付寶伺服器(商戶應用公鑰解密)
    	 * 支付寶向商戶發送異步的通知:支付寶伺服器(支付寶私鑰加密)--->商戶發起支付(支付寶公鑰解密)
    	 * 
    	 * 商戶(私鑰)發送請求向支付寶伺服器,支付寶伺服器用 商戶(公鑰)解密商戶發來的請求資訊。
    	 * 支付寶伺服器(私鑰)異步通知,發送給商戶(支付寶的公鑰)解密支付寶發來的異步通知消息。
    	 */
    }           
  2. 引入pom檔案

    <!--best-pay-sdk -->
    		<dependency>
    			<groupId>cn.springboot</groupId>
    			<artifactId>best-pay-sdk</artifactId>
    			<version>1.3.1</version>
    		</dependency>           
  3. 支付寶配置

    @Configuration
    public class BestPayConfig {
    	//微信和支付寶的參數
    	@Autowired
    	private WeachatProperties weachat;
    	@Autowired
    	private AliPayProperties alipay;
    
    	@Bean
    	public BestPayService BestPayconfig(WxPayConfig WxPayConfig) {
    		// 支付寶配置
    		AliPayConfig aliPayConfig = new AliPayConfig();
    		aliPayConfig.setAppId(alipay.getAppId());
    		aliPayConfig.setPrivateKey(alipay.getPrivateKey());
    		aliPayConfig.setAliPayPublicKey(alipay.getAliPayPublicKey());
    		aliPayConfig.setNotifyUrl(alipay.getNotifyUrl());// 支付寶異步通知資訊
    		aliPayConfig.setReturnUrl(alipay.getReturnUrl());// 支付成功之後轉跳到的頁面
    		// 實作支付服務接口==根據不同的支付方式 傳回對應的BestPayService對象
    		BestPayServiceImpl bestPay = new BestPayServiceImpl();
    		bestPay.setWxPayConfig(WxPayConfig);// 設定微信配置資訊
    		bestPay.setAliPayConfig(aliPayConfig);// 設定支付寶的配置資訊
    		return bestPay;
    	}
    	
    	//微信單獨配置是為了controller層 支付完成之後 轉跳頁面 而支付寶内部直接設定就好
    	@Bean
    	public WxPayConfig WxPayConfig() {
    		// 微信配置
    		WxPayConfig WxConfig = new WxPayConfig();
    		WxConfig.setAppAppId(weachat.getOPAppId());//商戶平台綁定的開放平台移動應用的openid
    		WxConfig.setAppId(weachat.getMPAppId());
    		WxConfig.setAppSecret(weachat.getMPSecret());
    		WxConfig.setMchId(weachat.getMchId());
    		WxConfig.setMchKey(weachat.getMchKey());
    		WxConfig.setKeyPath(weachat.getIDBook());
    		WxConfig.setNotifyUrl(weachat.getNotifyUrl());// 微信異步通知資訊
    		WxConfig.setReturnUrl(weachat.getReturnUrl());// 微信支付成功的傳回頁面
    		return WxConfig;
    	}
    	
    }           
  4. 支付寶支付

    // 微信和支付寶支付
    	public PayResponse createPay(String orderId,BestPayTypeEnum payType,String openid) {
    		//查詢訂單
    		OrderForm order=orders.selectByOrderId(orderId);
    		// 校驗目前訂單的支付狀态(支付與未支付)
    		if (!StringUtils.equals(order.getStatus().toString(), OrderStatus.WAITINGPAY.getStatus().toString())) {
    			throw new PayException("訂單支付狀态不正确");
    		}
    		// 支付請求
    		PayRequest request = new PayRequest();
    		request.setOpenid(openid);
    		request.setOrderId(orderId);// 訂單号
    		request.setOrderName(order.getOrderName());// 訂單名字
    		request.setOrderAmount(order.getPrice().doubleValue());// 訂單的總價
    		logger.info("訂單的總價:" + order.getPrice().doubleValue());
    		// 支付方式:微信NATIVE支付、WXPAY_APP方式和支付寶APP、ALIPAY_PC、ALIPAY_WAP方式選擇
    		request.setPayTypeEnum(payType);// 支付方式
    		return payService.pay(request);
    	}           
  5. 支付寶退款

    public ServerResponse<String> alipayRefundRequest(String orderId) throws AlipayApiException {
    		AlipayClient alipayClient = new DefaultAlipayClient(payConfig.getURL(),
    				payConfig.getAppId(), payConfig.getPrivateKey(), "json", "UTF-8",
    				payConfig.getAliPayPublicKey(), "RSA2");
    		AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
    		//根據訂單号查詢該訂單
    		OrderForm orderForm=orders.selectByOrderId(orderId);
    		if(orderForm==null){
    			return ServerResponse.createByError(ResponseCode.ERROR,"退款訂單号不存在");
    		}
    		AlipayRefund alipayRefund= new AlipayRefund();
    		alipayRefund.setOut_trade_no(orderForm.getOrderId());//這個是商戶的訂單号
    		alipayRefund.setTrade_no(orderForm.getOrderNum());//這個是支付寶的訂單号
    		alipayRefund.setRefund_amount(orderForm.getPrice().toString());//退款金額
    		request.setBizContent(JSONObject.toJSONString(alipayRefund));//2個都可以,這個參數的順序 不影響退款
    		AlipayTradeRefundResponse response = alipayClient.execute(request);
    		if (response.isSuccess()) {
    			orderForm.setRefuseTime(new Date());
    			orderForm.setStatus(OrderStatus.ORDERRFUSE.getStatus());
    			orders.updateById(orderForm);
    			//增加資金流水記錄
    			CashFlow cash=new CashFlow();
    			cash.setId(Md5SaltUtils.getStringId());
    			cash.setOrderFormId(orderForm.getId());
    			cash.setType(OrderStatus.ORDEROUTCOME.getStatus());
    			cash.setCreateTime(new Date());
    			cashflow.insert(cash);
    			return ServerResponse.createBySuccess("退款成功");
    		} else {
    			return ServerResponse.createByError("退款失敗",orderForm.getOrderId());
    		}
    	}           
  6. 支付寶回調

    // 異步通知:支付異步通知驗證是否支付成功
    	@Transactional
    	public String NotiyfiyInfor(String notiyBody) {
    		// 1.驗證簽名方式==防止在URL中修改參數資訊-以驗證微信傳回的加密字元串是否正确 修改訂單訂單資訊
    		PayResponse response = payService.asyncNotify(notiyBody);
    		// 2. 金額校驗(從資料庫查詢使用者支付訂單的金額與實際微信回調資訊中的訂單金額做對比)
    		//查詢訂單
    		OrderForm order=orders.selectByOrderId(response.getOrderId());
    		if (order != null) {
    			logger.info(String.format("異步通知支付的訂單号碼:%s,異步通知支付的訂單金額:%s", response.getOrderId(),response.getOrderAmount()));
    
    				// 資料庫訂單的金額與異步通知的訂單金額是否相等
    				if (order.getPrice().compareTo(BigDecimal.valueOf(response.getOrderAmount())) != 0) {
    					throw new PayException("資料庫訂單金額與異步通知的訂單金額不一緻:" + response.getOrderAmount());
    				}
    				// 3. 判斷訂單是否支付成功==>修改訂單的狀态
    				order.setStatus(OrderStatus.PAYED.getStatus());
    				// 交易流水号
    				logger.info("交易流水号==>" + response.getOutTradeNo());
    				order.setOrderNum(response.getOutTradeNo());
    				order.setType(response.getPayPlatformEnum().getName());
    				order.setPayTime(new Date());
    				//更新訂單資料訂單資訊
    				orders.updateById(order);
    				//增加資金流水記錄
    				CashFlow cash=new CashFlow();
    				cash.setId(Md5SaltUtils.getStringId());
    				cash.setOrderFormId(order.getId());
    				cash.setType(OrderStatus.ORDERINCOME.getStatus());
    				cash.setCreateTime(new Date());
    				cashflow.insert(cash);
    			}
    		// 以上校驗全部通過 判斷支付的平台是微信還是支付寶,傳回對應的格式的資訊==>就要告訴微信或者支付寶不要再通知了,否則會有時間間隔的有回調資訊發送給我們
    		if (response.getPayPlatformEnum() == BestPayPlatformEnum.WX) {
    			return "<xml>\n" + "<return_code><![CDATA[SUCCESS]]></return_code>\n"
    					+ "  <return_msg><![CDATA[OK]]></return_msg>\n" + "</xml>";
    		} else if (response.getPayPlatformEnum() == BestPayPlatformEnum.ALIPAY) {
    			return "success";
    		}
    		throw new PayException("訂單号不存在");
    	}           
  7. application.properties參數引入

    alipay.AppId=xxx
    alipay.PrivateKey=xxx
    alipay.AliPayPublicKey=xxxx
    alipay.ReturnUrl=http://xxx/order/return
    alipay.NotifyUrl=http://xxx/order/notify           
  8. 回掉和支付成功回掉頁面
    // 接收的異步通知
    	@ResponseBody
    	@PostMapping("/notify")
    	public String PayNotify(@RequestBody String notiyBody) {
    		return payService.NotiyfiyInfor(notiyBody);
    	}
    
    	// 支付成功==傳回支付成功的頁面
    	@ResponseBody
    	@GetMapping("/return")
    	public String PaySuccessfully() {
    		return "支付成功";
    	}           
  9. 發起支付
    @Transactional
    	@RequestMapping(value = "/alipay",method = RequestMethod.POST)
    	public ModelAndView AlipayPay(@RequestParam("orderId") String orderId,
    			@RequestParam("payType") BestPayTypeEnum paytype) {
    		Map<String, Object> map = new HashMap<String, Object>();
    		logger.info(String.format("支付寶開始支付:支付方式:%s,支付訂單号碼:%s", paytype, orderId));
    
    		PayResponse response = payService.createPay(orderId, paytype,"");
    		// 支付寶支付
    		if (paytype == BestPayTypeEnum.ALIPAY_PC) {
    			map.put("body", response.getBody());
    			return new ModelAndView("AlipayPC", map);
    		} else if (paytype == BestPayTypeEnum.ALIPAY_APP) {
    			map.put("body", response.getBody());
    			logger.info("ALIPAY_APP==>"+response.getBody());
    			return new ModelAndView("AlipayAPP", map);
    		} else if (paytype == BestPayTypeEnum.ALIPAY_WAP) {
    			map.put("body", response.getBody());
    			logger.info("ALIPAY_WAP==>"+response.getBody());
    			return new ModelAndView("AlipayWEB", map);
    		} 
    		throw new RuntimeException("支付狀态不合法");
    	}           
  10. 添加支付成功後的展示頁面
    整合支付寶支付與退款以及回調
  11.  如果您沒有密鑰的話 可以聯系我 我可以提供使用 私信聯系我 點贊+關注+評論

繼續閱讀