1. 程式人生 > 其它 >整合支付寶支付與退款以及回撥

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

技術標籤:支付支付寶支付javaspringboot

  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. 如果您沒有金鑰的話 可以聯絡我 我可以提供使用 私信聯絡我點贊+關注+評論