支付宝小程序支付 查询 退款 异步回调通知

最近在开发一款预约停车小程序, 记录一下使用支付宝支付api的流程,本文涉及到的是 公钥 加签方式

1.开发前的配置准备

1.1 创建小程序并上传审核

1.2 生成秘钥并上传

生成秘钥地址:跟着流程走即可

签名完成之后会自动生成支付宝公钥,需要记录保存

注释:在配置完签名之后可以获取支付宝公钥, 支付宝公钥唯一, 不会因为私钥和公钥的变换而改变
关于支付宝公钥的问题链接

如果做的项目是第三方平台(ISV)代替商户收款, 还是需要商户授权的(我做的就是这个)

2.通用配置

2.1 引入 maven 依赖

<dependency>
   <groupId>com.alipay.sdk</groupId>
   <artifactId>alipay-sdk-java</artifactId>
   <version>4.9.79.ALL</version>
</dependency>

添加配置信息

wensi:
  alipay:
    gatewayUrl: https://openapi.alipay.com/gateway.do
    appid: 小程序id
    appPrivateKey: 你的应用私钥
    alipayPublicKey: 生成的阿里公钥

2.2 AlipayProperties

@Data
@ConfigurationProperties(prefix = "pay.alipay")
public class AlipayProperties {
    /**
     * 支付宝gatewayUrl
     */
    private String gatewayUrl;
    /**
     * 商户应用id
     */
    private String appid;
    /**
     * RSA私钥,用于对商户请求报文加签
     */
    private String appPrivateKey;
    /**
     * 支付宝RSA公钥,用于验签支付宝应答
     */
    private String alipayPublicKey;

    /**
     * 签名类型
     */
    private String signType = "RSA2";

    /**
     * 格式
     */
    private String formate = "json";
    /**
     * 编码
     */
    private String charset = "UTF-8";

    /**
     * 同步地址
     */
    private String returnUrl;

    /**
     * 异步地址
     */
    private String notifyUrl;
}

AlipayClient

@Autowired
private AlipayProperties properties;

/**
 * 支付宝接口加签模式为公钥时使用
 */
@Bean
public AlipayClient alipayClient() {
    return new DefaultAlipayClient(properties.getGatewayUrl(), // 支付宝网关 唯一
            properties.getAppid(), // 小程序的appid
            properties.getAppPrivateKey(), // 生成的私钥
            properties.getFormate(),
            properties.getCharset(),
            properties.getAlipayPublicKey(), // 阿里公钥
            properties.getSignType());
}

调取支付接口

//将 alipayClient 注入进来
// 建议对入参进行验证
// 创建订单请求
AlipayTradeCreateRequest request = new AlipayTradeCreateRequest();
// 使用第三方代商户收款的时候传入
String appAuthToken = model.getAppAuthToken();
log.info("第三方授权token: {}", appAuthToken);
request.putOtherTextParam ("app_auth_token", appAuthToken );

//异步回掉地址
request.setNotifyUrl(notifyUrlConfig.getSelf());

//不想自己拼接 json 也可以使用对应的 model: AlipayTradeCreateModel
// 拼接请求 json
request.setBizContent("{" +
         "\"out_trade_no\":\""+thirdReq.getOutTradeNo()+"\"," + // 自己生产的订单号
         "\"total_amount\":"+realAmount.divide(new BigDecimal(100)).toString()+"," + // 金额
         "\"buyer_id\": "+ thirdReq.getBuyerId() + "," + // 购买者id,可以在授权的时候获取
         "\"subject\":\""+thirdReq.getSubject()+"\"" + "}"); // 支付标题

try {
    AlipayTradeCreateResponse response = alipayClient.execute(request);
    if (response.isSuccess()) {
    	// 创建订单成功 进行相应操作
        // tradeNo 需要给到前端,唤起支付请求
        String tradeNo = response.getTradeNo();
        log.info("创建当面付订单返回成功:订单编号:{}" , tradeNo);
    }else{
    	// 创建订单失败 进行相应操作
        log.info("创建当面付订单返回失败,返回信息:{}" , response.getMsg());
    }
} catch (AlipayApiException e) {
    e.printStackTrace();
}

buyer_id 在小程序支付中必须传入

官网创建订单链接

退款接口

// 建议对入参进行验证
// 创建退款请求
AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
// 拼接退款 json 
request.setBizContent("{" +
        "\"out_trade_no\":\""+h5Req.getOrderId()+"\"," + // 退款订单号, 建议使用 trade_no
        "\"refund_amount\":"+totalAmount.divide(new BigDecimal(100)).toString()+" "+"}"); // 退款金额
// 如果是第三方代商户收款, 需要传入授权token
String appAuthToken = tenantConfig.getAppAuthToken();
request.putOtherTextParam ("app_auth_token", appAuthToken );

try {
    AlipayTradeRefundResponse response = alipayClient.execute(request);
    if (response.isSuccess()) {
        // 退款成功之后的相应操作
        log.info("退款接口成功返回:{}", response);
    }else {
        // 退款失败之后的相应操作
        log.info("退款接口返回失败:{}", response);
    }
} catch (AlipayApiException e) {
    e.printStackTrace();
}

官网退款接口链接

订单查询接口

AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
request.setBizContent("{" +
"\"out_trade_no\":\"20150320010101001\"," +
"\"trade_no\":\"2014112611001004680 073956707\"," +
"\"org_pid\":\"2088101117952222\"," +
"      \"query_options\":[" +
"        \"trade_settle_info\"" +
"      ]" +
"  }");
AlipayTradeQueryResponse response = alipayClient.execute(request);
if(response.isSuccess()){
System.out.println("调用成功");
} else {
System.out.println("调用失败");
}

官网查询接口链接

异步回调通知

public String notify(HttpServletRequest request, HttpServletResponse httpServletResponse) {
log.info("-----------支付异步通知----------------");
// 获取支付宝回调通知参数
Map requestParams = request.getParameterMap();
log.info(">>>支付宝回调参数:{}", requestParams);
Map<String, String> params = new HashMap<>();
for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
    String name = (String) iter.next();
    String[] values = (String[]) requestParams.get(name);
    String valueStr = "";
    for (int i = 0; i < values.length; i++) {
        valueStr = (i == values.length - 1) ? valueStr + values[i]
                : valueStr + values[i] + ",";
    }
    //乱码解决,这段代码在出现乱码时使用。
    //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
    params.put(name, valueStr);
}
log.info(">>>支付宝回调参数解析:{}", params);

try {
	// 验签
    boolean signVerified = AlipaySignature.rsaCheckV1(params,
            mp.getAlipayPublicKey(),
            mp.getCharset(),
            mp.getSignType());

    if (signVerified) {
        log.info(">>>支付宝回调签名认证成功");
        //商户订单号
        String outTradeNo = params.get("out_trade_no");
        log.info("商户订单号===================>: {}", outTradeNo);
        //阿里订单号
        String tradeNo = params.get("trade_no");
        log.info("阿里订单号===================>: {}", tradeNo);
        //交易状态
        String trade_status = params.get("trade_status");
        log.info("回调的状态=============> {}", trade_status);
        
        String totalAmount = params.get("total_amount");
        BigDecimal a = new BigDecimal(totalAmount);
        log.info("总金额(单位:分)=================> {}", totalAmount);

        String buyerId = params.get("buyer_id");
        log.info("buyerId======================{}", buyerId);
		
		// 支付宝官网说订单状态只要为 TRADE_SUCCESS 即可
        if ("TRADE_SUCCESS".equals(trade_status) || "TRADE_FINISHED".equals(trade_status)) {
            log.info("-----------^v^支付成功^v^------------");
            // 更改订单状态,编写相应逻辑
        }
    } else {
        log.info("支付宝回调签名认证失败,signVerified=false, params:{}", params);
        //return "failure";
    }
} catch (AlipayApiException e) {
    e.printStackTrace();
    log.error(e.getMessage(), e);
    log.info("支付宝回调签名认证失败,signVerified=false, params:{}", params);
    //return "failure";
}
return "success";
}

支付宝说必须要打印 success ,才会停止发送异步通知,但是我在这边打印了反而还是显示错误.直接返回 string 类型的 success 反而没问题

异步查看回调结果,可以使用云排查
云排查连接

本人做的是单独的收银台模块,支持多方使用,如有需要,请加 QQ:2569905320

好记性不如烂笔头, 记录 加油

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值