支付宝支付(五):周期扣款-支付后签约场景

目录

一、调用APP支付接口,拉起支付宝,支付并签约页面

二、业务流程图

三、心声


一、调用APP支付接口,拉起支付宝,支付并签约页面

1、业务代码如下:

public AlipayTradeAppPayResponse payAndSignScene(AliPayBo bo) {
        try {
            log.info("------------------------开始初始化AliPay入参,订单号【{}】",bo.getOutTradeNo());
            // 也可以调用batchOptional扩展方法,批量设置可选业务参数(biz_content下的可选字段)
            Map<String, Object> optionalArgs = new HashMap<>();
            //该笔订单允许的最晚付款时间,逾期将关闭交易。取值范围:1m~15d,该参数数值不接受小数点,如 1.5h,可转换为 90m。
            optionalArgs.put("timeout_express", "30m");
            //订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000]
            optionalArgs.put("total_amount", bo.getTotalAmount());
            //周期扣款销售产品码固定为CYCLE_PAY_AUTH。
            optionalArgs.put("product_code", "CYCLE_PAY_AUTH");
            //交易标题
            optionalArgs.put("subject",bo.getSubject());
            //商户网站唯一订单号
            optionalArgs.put("out_trade_no",bo.getOutTradeNo());

            //---------------------------------------------设置签约参数:start-----------------------------
            Map<String, Object> signParams = new HashMap<>();
            //周期扣款个人签约产品码固定为CYCLE_PAY_AUTH_P
            signParams.put("personal_product_code","CYCLE_PAY_AUTH_P");
            //协议签约场景,参见下文sign_scene参数说明  INDUSTRY|EDU教育行业 TODO
            signParams.put("sign_scene", AliPayConstant.SIGN_SCENE);
            // 商户签约号,代扣协议中标示用户的唯一签约号(确保在商户系统中唯一) TODO
            signParams.put("external_agreement_no",bo.getExternalAgreementNo());

            /**请按当前接入的方式进行填充,且输入值必须为文档中的参数取值范围,
             * 1. ALIPAYAPP (钱包h5页面签约)
             * 2. QRCODE(扫码签约)
             * 3. QRCODEORSMS(扫码签约或者短信签约)*/
            Map<String, Object> accessParams = new HashMap<>();
            accessParams.put("channel","ALIPAYAPP");
            signParams.put("access_params",accessParams);

            /**周期管控规则参数period_rule_params,在签约周期扣款产品(如CYCLE_PAY_AUTH_P)时必传,在签约其他产品时无需传入。
             周期扣款产品,会按照这里传入的参数提示用户,并对发起扣款的时间、金额、次数等做相应限制 */
            Map<String, Object> periodRuleParams = new HashMap<>();
            //周期类型period_type是周期扣款产品必填,枚举值为DAY和MONTH
            periodRuleParams.put("period_type","DAY");
            //30天为一个扣款周期
            periodRuleParams.put("period","30");
            /**首次执行时间execute_time是周期扣款产品必填,即商户发起首次扣款的时间。精确到日,格式为yyyy-MM-dd
             结合其他必填的扣款周期参数,会确定商户以后的扣款计划。发起扣款的时间需符合这里的扣款计划
             首次扣款日期:当前时间+30  ; 目前允许商户在约定日期之前5天(不含扣款日当天)开始扣款
             */
            periodRuleParams.put("execute_time", bo.getExecuteTime());

            /**单次扣款最大金额single_amount是周期扣款产品必填,即每次发起扣款时限制的最大金额,单位为元。商户每次发起扣款都不允许大于此金额*/
            periodRuleParams.put("single_amount",bo.getSingleAmount());

            signParams.put("period_rule_params",periodRuleParams);

            //签约成功后商户用于接收异步通知的地址:如果不传入,签约与支付的异步通知都会发到外层notify_url参数传入的地址;TODO
            //signParams.put("sign_notify_url","");

            //签约参数。如果希望在sdk中支付并签约,需要在这里传入签约信息。周期扣款场景 product_code 为 CYCLE_PAY_AUTH 时必填
            optionalArgs.put("agreement_sign_params",signParams);
            //---------------------------------------------设置签约参数:end-----------------------------
            log.info("------------------------完成初始化AliPay入参,订单号【{}】,参数为【{}】",bo.getOutTradeNo(), JSONUtil.toJsonStr(optionalArgs));
            Long startTime = System.currentTimeMillis();
            log.info("------------------------开始-调用AliPay easySDK 执行同步支付异步签约,订单号【{}】",bo.getOutTradeNo());
            //1完成同步支付与异步签约,通过异步通知或者查询接口确认签约结果
            AlipayTradeAppPayResponse payResponse = Factory.Payment.App()
                    .batchOptional(optionalArgs)
                    .pay(bo.getSubject(),bo.getOutTradeNo(),bo.getTotalAmount());
            Long endTime = System.currentTimeMillis();
            log.info("------------------------完成-调用AliPay easySDK 执行同步支付异步签约,订单号【{}】,用时{}毫秒",bo.getOutTradeNo(),(endTime-startTime));
            if (ResponseChecker.success(payResponse)) {
                return payResponse;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

2、使用的是APP支付统一接口,只是入参多了签约的相关协议

二、业务流程图

1、

 2、关于生成预支付订单的,和后续支付结果查询,处理后续业务代码就根据个人业务场景处理,

3、我没有使用支付宝的异步通知的参数:notice_url ,都是使用定时任务根据业务表,代用支付宝官方接口来控制后续的逻辑,这点看个人选择了

三、心声

1、由于之前没做过支付宝周期扣款的业务,公司也没有人会,全靠个人看官网,频繁的咨询官方技术支持,不停的踩坑,总算把第一版的功能实现了,后续功能有优化的话,在补充文章

2、到此,支付宝支付相关的文章到此结束了,希望可以帮助刚入坑的同学们!

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
以下是一个简单的支付宝签约扣款的 Spring Boot 代码示例,需要您替换相应的参数并配置您的支付宝账户信息。 ```java import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayClient; import com.alipay.api.DefaultAlipayClient; import com.alipay.api.request.AlipayTradePayRequest; import com.alipay.api.request.AlipayUserAgreementPageSignRequest; import com.alipay.api.request.AlipayUserAgreementQueryRequest; import com.alipay.api.response.AlipayTradePayResponse; import com.alipay.api.response.AlipayUserAgreementPageSignResponse; import com.alipay.api.response.AlipayUserAgreementQueryResponse; import org.springframework.stereotype.Service; @Service public class AlipayService { private final AlipayConfig alipayConfig; public AlipayService(AlipayConfig alipayConfig) { this.alipayConfig = alipayConfig; } public void signAndPay() throws AlipayApiException { // 初始化 AlipayClient AlipayClient alipayClient = new DefaultAlipayClient( alipayConfig.getGatewayUrl(), alipayConfig.getAppId(), alipayConfig.getMerchantPrivateKey(), "json", alipayConfig.getCharset(), alipayConfig.getAlipayPublicKey(), alipayConfig.getSignType()); // 先发起签约请求 AlipayUserAgreementPageSignRequest signRequest = new AlipayUserAgreementPageSignRequest(); signRequest.setReturnUrl(alipayConfig.getReturnUrl()); signRequest.setNotifyUrl(alipayConfig.getNotifyUrl()); signRequest.setAgreementName("测试协议"); signRequest.setSignerName("张三"); signRequest.setSignerIdentityType("IDCARD"); signRequest.setSignerIdentityNo("123456789012345678"); signRequest.setPersonalProductCode("GENERAL_WITHHOLDING_P"); signRequest.setSignScene("INDUSTRY|CARRENTAL"); signRequest.setExternalAgreementNo("1234567890"); signRequest.setDeviceId("123456"); signRequest.setAppId(alipayConfig.getAppId()); signRequest.setAccessParams("{\"channel\":\"ALIPAYAPP\"}"); AlipayUserAgreementPageSignResponse signResponse = alipayClient.pageExecute(signRequest); String signResult = signResponse.getBody(); System.out.println(signResult); // 等待用户在支付宝页面确认签约后,获取签约结果 AlipayUserAgreementQueryRequest queryRequest = new AlipayUserAgreementQueryRequest(); queryRequest.setAgreementNo("202101010000000000001"); queryRequest.setProductCode("GENERAL_WITHHOLDING_P"); AlipayUserAgreementQueryResponse queryResponse = alipayClient.execute(queryRequest); String queryResult = queryResponse.getBody(); System.out.println(queryResult); if ("SUCCESS".equals(queryResponse.getStatus())) { // 签约成功,发起扣款请求 AlipayTradePayRequest payRequest = new AlipayTradePayRequest(); payRequest.setBizContent("{\"out_trade_no\":\"202101010000000000002\"," + "\"total_amount\":\"0.01\",\"subject\":\"测试商品\"," + "\"seller_id\":\"支付宝卖家ID\",\"buyer_id\":\"" + queryResponse.getPayerUserId() + "\"," + "\"auth_no\":\"" + queryResponse.getAgreementNo() + "\"," + "\"product_code\":\"GENERAL_WITHHOLDING\"}"); AlipayTradePayResponse payResponse = alipayClient.execute(payRequest); String payResult = payResponse.getBody(); System.out.println(payResult); } else { // 签约失败或者其他原因,处理异常情况 System.out.println("签约失败"); } } } ``` 需要注意的是,这只是一个简单的示例代码,具体实现过程中需要您根据自己的业务需求和接口文档进行相应的调整和修改。同时,建议您在测试环境中进行代码测试和调试,确保代码的正确性和稳定性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值