JAVA全系列 教程
3762个小节阅读:7092.4k
C语言快速入门
JAVA全系列 教程
面向对象的程序设计语言
Python全系列 教程
Python3.x版本,未来主流的版本
人工智能 教程
顺势而为,AI创新未来
大厂算法 教程
算法,程序员自我提升必经之路
C++ 教程
一门通用计算机编程语言
微服务 教程
目前业界流行的框架组合
web前端全系列 教程
通向WEB技术世界的钥匙
大数据全系列 教程
站在云端操控万千数据
AIGC全能工具班
A A
White Night
xxxxxxxxxx
{
"orderChargeDto": {
"chId": "CH1463686948676829184",
"orderAmount": 225,
"orderId": "ODC1460147514475937793",
"orderStatus": "0",
"patientName": "唐太宗",
"payTime": "yyyy-mm-dd 10:49:10",
"regId": "GH1463681727015813120"
},
"orderChargeItemDtoList": [{
"coId": "CO1463771831843553280",
"itemAmount": "225",
"itemId": "ITEM1463771832669831168",
"itemName": "血常规",
"itemNum": 1,
"itemPrice": 5,
"itemType": "1",
"orderId": "CO1463771831843553280",
"status": "0"
}]
}
返回JSON数据
名称 | 类型 | 其他信息 |
---|---|---|
msg | String | |
code | int | |
data | object | |
├─ allAmount | int | |
├─ orderId | String | |
├─ payUrl | String |
修改system-web模块下的pom.xml文件
xxxxxxxxxx
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>3.3.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/alipay-sdk-java-3.3.0.jar</systemPath>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>alipay-trade-sdk-java</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/alipay-trade-sdk-1.0.jar</systemPath>
</dependency>
xxxxxxxxxx
package com.bjsxt.config.pay;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.demo.trade.config.Configs;
import com.alipay.demo.trade.model.builder.AlipayTradePrecreateRequestBuilder;
import com.alipay.demo.trade.model.builder.AlipayTradeRefundRequestBuilder;
import com.alipay.demo.trade.model.result.AlipayF2FPrecreateResult;
import com.alipay.demo.trade.model.result.AlipayF2FRefundResult;
import com.alipay.demo.trade.service.AlipayTradeService;
import com.alipay.demo.trade.service.impl.AlipayTradeServiceImpl;
import lombok.extern.log4j.Log4j2;
import java.util.HashMap;
import java.util.Map;
/**
*
* 支付类
*/
public class PayService {
//支付宝网关支付的对象
static AlipayTradeService tradeService;
//初始化对象
static {
// 一定要在创建AlipayTradeService之前设置参数
Configs.init("zfbinfo.properties");
tradeService = new AlipayTradeServiceImpl.ClientBuilder().build();
}
// 商户操作员编号,添加此参数可以为商户操作员做销售统计
static String operatorId = "test_operator_id";
// (必填) 商户门店编号,通过门店号和商家后台可以配置精准到门店的折扣信息,详询支付宝技术支持
static String storeId = "test_store_id";
// 支付超时,定义为120分钟
static String timeoutExpress = "120m";
/**
* 支付的方法
* @param outTradeNo (必填) 商户网站订单系统中唯一订单号,64个字符以内,只能包含字母、数字、下划线, 需保证商户系统端不能重复,建议通过数据库sequence生成,
* @param subject (必填) 订单标题,粗略描述用户的支付目的。如“喜士多(浦东店)消费”
* @param totalAmount (必填) 订单总金额,单位为元,不能超过1亿元
* @param undiscountableAmount (可选) 订单不可打折金额,可以配合商家平台配置折扣活动,如果酒水不参与打折,则将对应金额填写至此字段
* @param body 订单描述,可以对交易或商品进行一个详细地描述,比如填写"购买商品2件共15.00元"
* @param notifyUrl /支付宝服务器主动通知商户服务器里指定的页面http路径,根据需要设置
* @return
*/
public static Map<String,Object> pay(String outTradeNo,
String subject,
String totalAmount,
String undiscountableAmount,
String body,
String notifyUrl
){
System.out.println(notifyUrl);
AlipayTradePrecreateRequestBuilder builder =new AlipayTradePrecreateRequestBuilder()
.setSubject(subject)
.setTotalAmount(totalAmount)
.setOutTradeNo(outTradeNo)
.setUndiscountableAmount(undiscountableAmount)
.setBody(body)
.setOperatorId(operatorId)
.setStoreId(storeId)
.setTimeoutExpress(timeoutExpress)
.setNotifyUrl(notifyUrl);
//发起支付
AlipayF2FPrecreateResult result = tradeService.tradePrecreate(builder);
Map<String,Object> map=new HashMap<>();
String msg;
Integer code;
switch (result.getTradeStatus()) {
case SUCCESS:
log.info("支付宝预下单成功: )");
AlipayTradePrecreateResponse res = result.getResponse();
//得到支付码,本质就是一个URL
String qrCode=res.getQrCode();
map.put("qrCode",qrCode);
msg="下单成功";
code=200;
break;
case FAILED:
log.error("支付宝预下单失败!!!");
msg="下单失败";
code=500;
break;
case UNKNOWN:
log.error("系统异常,预下单状态未知!!!");
msg="系统异常";
code=404;
break;
default:
log.error("不支持的交易状态,交易返回异常!!!");
msg="不支持的交易状态";
code=404;
break;
}
map.put("msg",msg);
map.put("code",code);
return map;
}
/**
* 退费
* @param outTradeNo 外部应该交易ID
* @param tradeNo 平台在支付成之后返回的平台【属于支付宝平台的ID】
* @param refundAmount 退款金额
* @param refundReason 退款原因
* @param outRequestNo 是否支持部分退款
*/
public static Map<String,Object> payBack(String outTradeNo,String tradeNo,String refundAmount,String refundReason,String outRequestNo){
AlipayTradeRefundRequestBuilder builder = new AlipayTradeRefundRequestBuilder()
.setOutTradeNo(outTradeNo)//outTradeNo tradeNo只需要有一个就行
.setTradeNo(tradeNo)
.setRefundAmount(refundAmount)
.setRefundReason(refundReason)
.setOutRequestNo(outRequestNo)
// .setNotifyUrl(notifyUrl)//没有用 因为这个回调地址就是收费时的回调地址
.setStoreId(storeId);
//退费请求
AlipayF2FRefundResult result = tradeService.tradeRefund(builder);
Map<String,Object> map=new HashMap<>();
Integer code=null;
String msg="";
switch (result.getTradeStatus()) {
case SUCCESS:
log.info("支付宝退款成功: )");
code=200;
msg="支付宝退款成功";
map.put("tradeNo",result.getResponse().getTradeNo());
break;
case FAILED:
log.error("支付宝退款失败!!!");
code=500;
msg="支付宝退款失败";
break;
case UNKNOWN:
log.error("系统异常,订单退款状态未知!!!");
code=500;
msg="系统异常,订单退款状态未知!!!";
break;
default:
log.error("不支持的交易状态,交易返回异常!!!");
code=500;
msg="不支持的交易状态,交易返回异常!!!";
break;
}
map.put("code",code);
map.put("msg",msg);
return map;
}
}
创建zfbinfo.properties
xxxxxxxxxx
# 支付宝网关名、partnerId和appId 注意测试和正式环境
open_api_domain = https://openapi.alipaydev.com/gateway.do
mcloud_api_domain = http://mcloudmonitor.com/gateway.do
pid = 此处请填写你的PID
appid = 2021000118647783
# RSA私钥、公钥和支付宝公钥
private_key = MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCHVgNRFXlkToWHFE0rPYPKq7ULyepSJ9ugqXhE/TpG76tf+/Ki5BSpzjwLAXEYlTKcX5/VUU4t8+ecrJTsEkIk2A3qNPc/3XFbzmu5Mzx1pGEMU7LTMeBHOPp1mTMK5sqBUpKZ2o0XndZ6bhRi5IWVsSAA9aD98CdrtvmtpH5/fsZWCtffCkc+PrJqla8eM5K3TH7AdI0tbAhpqH1HmYNERCPpY0n7hiCR57HsE+Ug/4ekwK4SYPSdTjRznZwjHbv5R7JU54a5OnNMNFalm8QZ1Z0Xcu49KEfXrlkNRBxL60Q1c/wA9pbdd/3Wl+L5TzLKw9udG6amX+FGYXqyfY1ZAgMBAAECggEAS5exlpLGEU8Cqmaei+56NLQgFgucRHNa66x9Lxu6d3DbamuSJYX8PLSjOQp/H1oGwO1wm3gkkOpRjmOfcxTnuSQrUp+mKrdrotLN3q8Y7JuWBVxHe0ilzTEhcCFTM+9shY6p9cJmK+SuPW4WFUA11cNPCLtT7T+EOKP1eYtuexoq3XwZOMtYOPeGSBGrCHy0htjiufgRcBlzcuJLgONfR+HBgHLZNFRqvnz3gvTVeJIePpwbLPJqvcc+Y9qh+7hI0040Npl87tC4nVkX/4oAj5M+Keht5ucQa3OLiMVqnWfIj82dYw85CExlkAQ7xAnG8VB/V7jUGCJQdwryf4QKBgQDDF8mp4JbfuWowzLDI27h22SbB5hWCVZPX5KoUvlbNRR3IeJJthny4YjlcdBdjzG15L4qX6RUzwkSkRyi264fuIJYBotd7UY2pi2De8oqoCoq0lj7b7rG+EC3Z/02dj1VSePUBl/ExMQeI6HHMFHfs1+aNPb1JR/9oRBEbrhWOFQKBgQCxllU5K9N/vGlqf0AboiGMOVivcbgs030X5dFrVmS8NXI60ltzyVidk/Qtwr/J6gS9FWA9z0myCKmrY3ICOVLEsfTur8ieokJndU/7Mz8OGPF87P1N5IN2kRg03Jr1QkscLpb3Wa64TKaSi3Y51/6TWxa3agoUe7blMxW1T0ZXNQKBgFGAt5QLqpwuhsl6SgSvnkGweHua1rOLcudHtTJTTkoVLNsaW/n7rFEPX+1a5oaf2cA990V9b4kfCLQkskKw5Sm7XU+zqxfuuyLwgnjBlOGc/dNxzTLuZj0D31PqT4+aWMfKlnii9HVbiU1N5nSevHcqvzuUZmad+HqjrQ4GTST9AoGAf3A4XDydHA9jPq9um+XvWSdWAyECX/iszld3vyVSSNW50YhfZGnbE8m28pfM9eLf36jVVcXJRt98kqdci0gDo29pK1guCdi6+m9vI/8UgtNXiKSw6hLQXGenDVg6Q0J9kA3G/F35SfyHlKZMAxqDb89wL9MCxMw65aORMnlfKvkCgYAYbYPCziMX2TwKzrWwm9CXnlyrjmM5EXhkg7xSCwr+bMuANQemiSbExj4qmtI7kfvvD0WtXIEEdHluGwKTFVQRBU3FWSvALXouJmG0Wh+IOPboMvtyCbPmz7/q17wCG2J6FfD1bEUBUq93J9I753da8YW2JbP6f2MHNpmPHQt7Hg==
public_key = MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAh1YDURV5ZE6FhxRNKz2Dyqu1C8nqUifboKl4RP06Ru+rX/vyouQUqc48CwFxGJUynF+f1VFOLfPnnKyU7BJCJNgN6jT3P91xW85ruTM8daRhDFOy0zHgRzj6dZkzCubKgVKSmdqNF53Wem4UYuSFlbEgAPWg/fAna7b5raR+f37rX3wpHPj6yapWvHjOSt0x+wHSNLWwIaah9R5mDREQj6WNJ+4Ygkeex7BPlIP+HpMCuEmD0nU40c52cIx27+UeyVOeGuTpzTDRWpZvEGdWdF3LuPShH165ZDUQcS+tENXP8APaW3Xf91pfi+U8yysPbnRumpl/hRmF6sn2NWQIDAQAB
#SHA1withRsa对应支付宝公钥
#alipay_public_key = MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDI6d306Q8fIfCOaTXyiUeJHkrIvYISRcc73s3vF1ZT7XN8RNPwJxo8pWaJMmvyTn9N4HQ632qJBVHf8sxHi/fEsraprwCtzvzQETrNRwVxLO5jVmRGi60j8Ue1efIlzPXV9je9mkjzOmdssymZkh2QhUrCmZYI/FCEa3/cNMW0QIDAQAB
#SHA256withRsa对应支付宝公钥
alipay_public_key = MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkloioiI10m9CGgEpxXtCXzOEQXb3Rm2xslqjc6iPJ0NDs5koXy8lFNm9n2iZAH7rSQjFKJxxs/e4uQrei535sfVtEM2Wz7WVdkOHRGj7mQHZvJFVFhazBRxMqR3HagDCImCGG/+X6QKFFxfMxxYgWK33eLaTNeAXPsR3JhMxXc1NMu8XpZIcallX+8du1Rs63+k4mkGG1iuXafxA0magdFUMnx9CxzCZCd5+945fYRYVB7v2OaBCl3djLlusijj3OVWfEP8ZQ3DcQW38WXAPhacru+HBzxedgJGD6sxt3sZLt5Ki47djTlx5WDaH5hayhD/MC7sYhfnCLI3+JwIDAQAB
# 签名类型: RSA->SHA1withRsa,RSA2->SHA256withRsa
sign_type = RSA2
# 当面付最大查询次数和查询间隔(毫秒)
max_query_retry = 5
query_duration = 5000
# 当面付最大撤销次数和撤销间隔(毫秒)
max_cancel_retry = 3
cancel_duration = 2000
# 交易保障线程第一次调度延迟和调度间隔(秒)
heartbeat_delay = 5
heartbeat_duration = 900
创建AliConfig类
xxxxxxxxxx
package com.bjsxt.config.pay;
/**
*
*/
public class AlipayConfig {
//应用的ID,申请时的APPID
public static String app_id = "2030000118647783";
//SHA256withRsa对应支付宝公钥
public static String alipay_public_key = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkloioiI10m9CGgEpxXtCXzOEQXb3Rm2xslqjc6iPJ0NDs5koXy8lFNm9n2iZAH7rSQjFKJxx4uQrei535bIimsfVtEM2Wz7WVdkOHRGj7mQHZvJFVFhazBRxMqR3HagDCImCGG/+X6QKFFxfMxxYgWK33eLaTNeAXPsR3JhMxXc1NMu8XpZIcallX+8du1Rs63+k4mkGG1iuXafxA0magdFUMnx9CxzCZCd5+945fYRYVB7v2OaBCl3djLlusijj3OVWfEP8ZQ3DcQW38WXAPhacru+HBzxedgJGD6sxt3sZLt5Ki47djTlx5WDaH5hayhD/MC7sYhfnCLI3+JwIDAQAB";
//签名方式
public static String sign_type = "RSA2";
//字码编码格式
public static String charset = "utf-8";
//回调地址
public static String notifyUrl="http://45314rh250.qicp.vip/pay/callback/";
}
在OrderChargeService及impl中增加根据订单id查询的方法
xxxxxxxxxx
public OrderCharge queryOrderChargeByOrderId(String orderId) {
return this.orderChargeMapper.selectById(orderId);
}
增加支付宝支付方法
xxxxxxxxxx
/**
* 创建支付宝收费订单
*/
"createOrderChargeWithZfb") (
public AjaxResult createOrderChargeWithZfb( OrderChargeFromDto orderChargeFromDto){
//1,保存订单
orderChargeFromDto.getOrderChargeDto().setPayType(Constants.PAY_TYPE_1);//支付宝支付
orderChargeFromDto.setSimpleUser(ShiroSecurityUtils.getCurrentSimpleUser());
String orderId = IdGeneratorSnowflake.generatorIdWithProfix(Constants.ID_PROFIX_ODC);
orderChargeFromDto.getOrderChargeDto().setOrderId(orderId);
this.orderChargeService.saveOrderAndItems(orderChargeFromDto);
//2,因为是支付宝支付,所以我们要返回给页面一个二维码
String outTradeNo=orderId;
String subject="SXT-医疗管理系统支付平台";
String totalAmount=orderChargeFromDto.getOrderChargeDto().getOrderAmount().toString();
String undiscountableAmount=null;
String body="";
List<OrderChargeItemDto> orderChargeItemDtoList = orderChargeFromDto.getOrderChargeItemDtoList();
for (OrderChargeItemDto orderChargeItemDto : orderChargeItemDtoList) {
body+=orderChargeItemDto.getItemName()+"-"+orderChargeItemDto.getItemPrice()+" ";
}
String notifyUrl= AlipayConfig.notifyUrl+outTradeNo;
Map<String, Object> pay = PayService.pay(outTradeNo, subject, totalAmount, undiscountableAmount, body, notifyUrl);
String qrCode = pay.get("qrCode").toString();
if(StringUtils.isNotBlank(qrCode)){
//创建支付成功
Map<String,Object> map=new HashMap<>();
map.put("orderId",orderId);
map.put("allAmount",totalAmount);
map.put("payUrl",qrCode);
return AjaxResult.success(map);
}else{
return AjaxResult.fail(pay.get("msg").toString());
}
}
生成PayController
xxxxxxxxxx
package com.bjsxt.controller.doctor;
import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.bjsxt.config.pay.AlipayConfig;
import com.bjsxt.constants.Constants;
import com.bjsxt.service.OrderChargeService;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
/**
*
*/
"pay") (
public class PayController {
private OrderChargeService orderChargeService;
"callback/{orderId}") (
public void callback( String orderId, HttpServletRequest request) {
Map<String, String> parameterMap = this.getParameterMap(request);
String trade_status = parameterMap.get("trade_status");
if ("TRADE_SUCCESS".equals(trade_status)) {
try {
//验证是否为支付宝发来的信息
boolean singVerified = AlipaySignature.rsaCheckV1(parameterMap, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type);
System.out.println(singVerified);//只有支付宝调用我们系统的接口才能去更新系统订单状态
log.info("验证签名结果{}:" + singVerified);
String refund_fee = parameterMap.get("refund_fee");
if (StringUtils.isNotBlank(refund_fee)) {
//说明是退费
System.out.println("退费成功:退费的子订单ID为:" + parameterMap.get("out_biz_no"));
//更新订单状态
} else {
//说明支付
String trade_no = parameterMap.get("trade_no");
System.out.println("收费成功,平台ID" + trade_no);
orderChargeService.paySuccess(orderId,trade_no, Constants.PAY_TYPE_1);
}
System.out.println(JSON.toJSON(parameterMap));
} catch (AlipayApiException e) {
e.printStackTrace();
log.error(orderId + "验证签名出现异常");
}
}else if("WAIT_BUYER_PAY".equals(trade_status)){
System.out.println("二维码已扫描,等待支付");
}
}
/**
* 获取request中的参数集合转Map
* Map<String,String> parameterMap = RequestUtil.getParameterMap(request)
*
* @param request
* @return
*/
public Map<String, String> getParameterMap(HttpServletRequest request) {
Map<String, String> map = new HashMap<>();
Enumeration<String> paramNames = request.getParameterNames();
while (paramNames.hasMoreElements()) {
String paramName = paramNames.nextElement();
String[] paramValues = request.getParameterValues(paramName);
if (paramValues.length == 1) {
String paramValue = paramValues[0];
if (paramValue.length() != 0) {
map.put(paramName, paramValue);
}
}
}
return map;
}
}
回调成功时输出的日志
xxxxxxxxxx
{"gmt_create":"2030-02-12 22:28:35","charset":"utf-8","seller_email":"drfbvt4315@sandbox.com","gmt_payment":"2030-02-12 22:28:59","notify_time":"2030-02-12 22:29:00","subject":"SXT-医疗管理系统支付平台","body":"买药用的","buyer_id":"2088622957171561","invoice_amount":"100.00","version":"1.0","notify_id":"2030021200222222900071560518527657","fund_bill_list":"[{\"amount\":\"100.00\",\"fundChannel\":\"ALIPAYACCOUNT\"}]","notify_type":"trade_status_sync","out_trade_no":"OD123124124ABCDE94","total_amount":"100.00","trade_status":"TRADE_SUCCESS","trade_no":"2030021222001471560502052486","auth_app_id":"2021000118647783","receipt_amount":"100.00","buyer_logon_id":"pxw***@sandbox.com","point_amount":"0.00","buyer_pay_amount":"100.00","app_id":"2021000118647783","seller_id":"2088621957091949"}
xxxxxxxxxx
#shiro配置
shiro
anon-urls
/login/doLogin*
/login/captcha*
/login/logout*
/druid/**
/pay/callback/**
authc-urls
/**
创建支付宝订单/doctor/charge/createOrderChargeWithZfb