package com.cyjd.rights.controller; import com.alibaba.fastjson.JSON; import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayConstants; import com.alipay.api.CertAlipayRequest; import com.alipay.api.internal.util.AlipaySignature; import com.alipay.api.response.AlipayTradePayResponse; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.cyjd.rights.beans.AliPayProperties; import com.cyjd.rights.beans.R; import com.cyjd.rights.business.service.AliPayOrderService; import com.cyjd.rights.business.service.AliPayService; import com.cyjd.rights.business.service.AliPaySigningOrderService; import com.cyjd.rights.constant.AliPayConstant; import com.cyjd.rights.constant.EnumPeriodType; import com.cyjd.rights.dto.AliPayInOrderByAgreementDto; import com.cyjd.rights.dto.AliPaySignUpDto; import com.cyjd.rights.entity.AliPayOrderEntity; import com.cyjd.rights.entity.AliPaySigningOrderEntity; import com.cyjd.rights.result.FResult; import com.cyjd.rights.utils.EntityConvertUtil; import com.cyjd.rights.utils.OrderUtil; import com.cyjd.rights.vo.AliPayInOrderByAgreementReq; import com.cyjd.rights.vo.AliPayQueryPageSignReq; import com.cyjd.rights.vo.AliPayTradeQueryReq; import com.cyjd.rights.vo.AliPayUserPageSignReq; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.java.Log; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.*; import javax.annotation.PostConstruct; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.time.LocalDateTime; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; /** * @author :WXC * @Date :2023/05/16 * @description : */ @Component @Api(tags = "阿里支付测试") @RestController @RequestMapping("/alipay") @Slf4j public class AliPayController { @Autowired private AliPayService aliPayService; @Autowired private AliPayOrderService aliPayOrderService; @Autowired private AliPaySigningOrderService aliPaySigningOrderService; /** * 支付配置 */ @Resource private AliPayProperties aliPayProperties; private CertAlipayRequest certAlipayRequest; private static String[] unicom = {"130", "131", "132", "140", "155", "156", "185", "186", "145", "171", "176", "175", "166"}; private static String[] mobileArray = {"134", "135", "136", "137", "138", "139", "147", "150", "151", "152", "157", "158", "159", "178", "182", "183", "184", "187", "188", "195", "198"}; private static String[] tel = {"133", "153", "177", "180", "181", "189", "173", "149", "199"}; @PostConstruct public void init() { CertAlipayRequest certAlipayRequest = new CertAlipayRequest(); //设置文件地址 // if (isSkipSign) { // aliPayProperties.setCertPath("D:\\daima\\hy\\ringback-q\\02Ypcl\\01Code\\01Plantform\\Server\\vrbt-client-controller\\src\\main\\resources\\config\\"); // } else { // aliPayProperties.setCertPath("/home/ypcl/server-client/config/"); // } certAlipayRequest.setServerUrl(AliPayConstant.serverUrl); certAlipayRequest.setAppId(aliPayProperties.getAppId()); certAlipayRequest.setPrivateKey(aliPayProperties.getPrivateKey()); certAlipayRequest.setFormat(AlipayConstants.FORMAT_JSON); certAlipayRequest.setCharset(AlipayConstants.CHARSET_UTF8); certAlipayRequest.setSignType(AlipayConstants.SIGN_TYPE_RSA2); certAlipayRequest.setCertPath(aliPayProperties.getCertPath() + "appCertPublicKey_" + aliPayProperties.getAppId() + ".crt"); certAlipayRequest.setAlipayPublicCertPath(aliPayProperties.getCertPath() + "alipayCertPublicKey_RSA2.crt"); certAlipayRequest.setRootCertPath(aliPayProperties.getCertPath() + "alipayRootCert.crt"); this.certAlipayRequest = certAlipayRequest; } @ApiOperation(value = "支付宝签约", notes = "前端先调用此接口,由服务端请求支付宝组装scheme地址,之后前端通过该地址唤起支付宝进行签约") @PostMapping("/signUp") public R signUp(@RequestBody AliPaySignUpDto signUpDto) { String price="19.9"; //查询数据库用户签约记录 AliPayUserPageSignReq signReq = new AliPayUserPageSignReq(); signUpDto.setIsPage(true); signUpDto.setPeriod("31"); //设置天数 signUpDto.setSingleAmount(price); //设置金额 signReq.setBusinessType(2); signReq.setType(0); String agreementNo = OrderUtil.getAgreementNo(); int i = checkFrom(signUpDto.getMobile()); //如果未签约,调用支付宝接口获取支付宝签约跳转地址 signReq.setExternalAgreementNo(agreementNo); signReq.setIsPage(signUpDto.getIsPage()); AliPayUserPageSignReq.PeriodRuleParams periodRuleParams = new AliPayUserPageSignReq.PeriodRuleParams(); periodRuleParams.setPeriod(signUpDto.getPeriod()); periodRuleParams.setPeriodType(EnumPeriodType.DAY); periodRuleParams.setSingleAmount(signUpDto.getSingleAmount()); signReq.setPeriodRuleParams(periodRuleParams); //aliPayUserPageSignReq.setSignScene("INDUSTRY|DIGITAL_MEDIA"); String signUrl = aliPayService.signUp(signReq); //保存签约订单 AliPaySigningOrderEntity aliPaySigningOrderEntity = new AliPaySigningOrderEntity(); aliPaySigningOrderEntity.setOrderId(agreementNo); aliPaySigningOrderEntity.setOrderTime(LocalDateTime.now()); aliPaySigningOrderEntity.setMobile(signUpDto.getMobile()); aliPaySigningOrderEntity.setLinkId(signUpDto.getLinkId()); aliPaySigningOrderEntity.setLinkName("推广名字"); //先定死 aliPaySigningOrderEntity.setOperatorsId(1); //先定死可能不要这个参数 aliPaySigningOrderEntity.setIsPage(signUpDto.getIsPage()?1:0); aliPaySigningOrderEntity.setOrderName("优爱腾三方权益业务"); aliPaySigningOrderEntity.setPrice(price); aliPaySigningOrderEntity.setBusinessType(1); if (StringUtils.isBlank(signUrl)) { aliPaySigningOrderEntity.setStatus(0); aliPaySigningOrderService.save(aliPaySigningOrderEntity); return R.error("签约失败,请重试"); } aliPaySigningOrderEntity.setStatus(2); aliPaySigningOrderEntity.setOpenAddress(signUrl); aliPaySigningOrderService.save(aliPaySigningOrderEntity); return R.ok().put("result", signUrl).put("signOrderId", agreementNo); } @ApiOperation(value = "支付宝签约状态查询", notes = "签约成功以后前端可调用此接口查询是否签约成功") @PostMapping("/querySign") public FResult querySign(@RequestParam String externalAgreementNo) { AliPayQueryPageSignReq aliPayQueryPageSignReq = new AliPayQueryPageSignReq(); aliPayQueryPageSignReq.setExternalAgreementNo(externalAgreementNo); boolean querySign = aliPayService.querySign(aliPayQueryPageSignReq); return FResult.ok(querySign); } @ApiOperation(value = "支付宝支付状态查询", notes = "代扣以后可调用此接口查询是否成功") @PostMapping("/queryOrder") public FResult queryOrder(@RequestParam String outTradeNo) { AliPayTradeQueryReq aliPayTradeQueryReq = new AliPayTradeQueryReq(); aliPayTradeQueryReq.setOutTradeNo(outTradeNo); boolean queryOrder = aliPayService.queryOrder(aliPayTradeQueryReq); return FResult.ok(queryOrder); } // @ApiOperation(value = "支付宝代扣", notes = "签约完成以后,通过支付宝签约号进行代扣操作,签约号需要在签约回调中获取并保存到数据库中,之后通过定时任务轮询扫描数据库进行代扣") // @PostMapping("/agreementPay") // public FResult agreementPay(@RequestBody AliPayInOrderByAgreementDto inOrderByAgreementDto) { // //AliPayEntity aliPayEntity = aliPayService.getOne(new QueryWrapper().eq("mobile", inOrderByAgreementDto.getMobile()).eq("type", 1).eq("status", 1).orderByDesc("order_time")); // inOrderByAgreementDto.setAuthCode("签约号"); // inOrderByAgreementDto.setSubject("会员随心选"); // inOrderByAgreementDto.setTotalAmount("19.90"); // String outTradeNo = OrderUtil.getOutTradeNo(); // inOrderByAgreementDto.setOutTradeNo(outTradeNo); // AliPayInOrderByAgreementReq payInOrderByAgreementReq = EntityConvertUtil.copy(inOrderByAgreementDto, AliPayInOrderByAgreementReq.class); // AlipayTradePayResponse alipayTradePayResponse = aliPayService.aliPayTradePayByAgreement(payInOrderByAgreementReq); // return FResult.ok(alipayTradePayResponse); // } @ApiOperation(value = "支付宝签约回调", notes = "签约完成后由支付宝发起,服务端根据回调的数据入库") @PostMapping("/signNotify") public String signNotify(HttpServletRequest request) { // 获取支付宝的请求信息 Map inMap = getNotifyMap(request); if (inMap == null) { return "fail"; } return signNotify(inMap); } @ApiOperation(value = "代扣回调", notes = "定时周期任务代扣结果通知") @PostMapping("/agreementNotify") public String agreementNotify(HttpServletRequest request) { // 获取支付宝的请求信息 Map inMap = getNotifyMap(request); if (inMap == null) { return "fail"; } String result = agreementNotify(inMap); return result; } //@Scheduled(cron = "0 0 8,20 * * ?") /** * 获取请求参数转为map * * @param request * @return */ private static Map getNotifyMap(HttpServletRequest request) { // 获取支付宝的请求信息 Map map = new HashMap<>(); Map requestParams = request.getParameterMap(); if (requestParams.isEmpty()) { return null; } //将 Map 转为 Map for (String name : requestParams.keySet()) { String[] values = requestParams.get(name); String valueStr = ""; for (int i = 0; i < values.length; i++) { valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ","; } map.put(name, valueStr); } return map; } /** * 签约 * { * "external_agreement_no":"Y2023052217492063821000", * "product_code":"CYCLE_PAY_AUTH", * "personal_product_code":"CYCLE_PAY_AUTH_P", * "sign_scene":"INDUSTRY|MOBILE", * "access_params":{ * "channel":"ALIPAYAPP" * }, * "period_rule_params":{ * "period":"7", * "period_type":"DAY", * "execute_time":"2023-05-22", * "single_amount":"0.01" * } * } * * @param aliPayUserPageSignReq * @return */ public String signUp(AliPayUserPageSignReq aliPayUserPageSignReq) { return null; } /** * 签约回调通知 * { * "charset":"UTF-8", * "notify_time":"2023-05-22 17:50:02", * "alipay_user_id":"2088722249554680", * "sign":"SbhJupeGzltbiNwbiZJd8u6+V9RXrQYfSo5b0kZYW5ayfmF+7eVCSlB+hhZTa0rzhNQMy0eiYxjCZG9NSq0V8E72Q5IT2vqPiL3BIIo49/zP8fW1PSoJyrH6wwJ45oOV05kOyMc9XbhMSnCxkvzJmVX4VunsKtDh7SJYuVLSmzlW1Afk12L45KSAIzebTIbSJX4RxxpRRZz3XpMAYT2wovqJCBL59boMv0ze+6yO/lPuq5Fl1K+uCU9mSvd2LvwC0rBDluE9i6Ri5s/23t7KGoKvKZRZbzVx6Z1EC+8q0qWVlh4urMMKnttBfTiSAsdp09zZUlQWFj4lP1gw8ckREQ==", * "external_agreement_no":"Y2023052217492063821000", * "version":"1.0", * "sign_time":"2023-05-22 17:50:02", * "notify_id":"2023052201222175002009751491422699", * "notify_type":"dut_user_sign", * "agreement_no":"20235322942117682668", * "invalid_time":"2115-02-01 00:00:00", * "auth_app_id":"2021003127667792", * "personal_product_code":"CYCLE_PAY_AUTH_P", * "valid_time":"2023-05-22 17:50:02", * "//login_token":"a8c9583559c99df56f59d6ae1f8b9580_68", * "app_id":"2021003127667792", * "sign_type":"RSA2", * "sign_scene":"INDUSTRY|MOBILE", * "status":"NORMAL", * "alipay_//logon_id":"151******06" * }external_agreement_no -> Y2023052220155843561000 * * @param inMap * @return */ public String signNotify(Map inMap) { log.info("===========================我是签约回调============================"); //log.info("支付宝签约回调开始:request{}", JSON.toJSONString(inMap)); try { //验签 boolean signVerified = AlipaySignature.certVerifyV1(inMap, certAlipayRequest.getAlipayPublicCertPath(), AlipayConstants.CHARSET_UTF8, AlipayConstants.SIGN_TYPE_RSA2); if (signVerified) { //按照支付结果异步通知中的描述,对支付结果中的业务内容进行1\2\3\4二次校验,校验成功后在response中返回success //协议状态,NORMAL:正常。UNSIGN:解约。 String status = inMap.get("status"); //代扣协议中标示用户的唯一签约号,商家自定义。仅签约接口传入时返回。 String externalAgreementNo = inMap.get("external_agreement_no"); //支付宝系统中用以唯一标识用户签约记录的编号。 String agreementNo = inMap.get("agreement_no"); //异步通知类型,dut_user_sign:当 status = NORMAL 表示签约成功。dut_user_unsign:当 status = UNSIGN 表示解约成功。 String notifyType = inMap.get("notify_type"); //签约协议场景。 String signScene = inMap.get("sign_scene"); //协议产品码。 String personalProductCode = inMap.get("personal_product_code"); //用户的支付宝账号对应的支付宝唯一用户号。 String alipayUserId = inMap.get("alipay_user_id"); //用户的支付宝登录账号。 String alipayLogonId = inMap.get("alipay_//logon_id"); log.info("支付宝签约回调通知:" + inMap.toString()); //更新订单签约信息 AliPaySigningOrderEntity aliPaySigningOrder = aliPaySigningOrderService.getOne(new QueryWrapper().eq("order_id", externalAgreementNo)); if (aliPaySigningOrder==null){ return "fail"; } aliPaySigningOrder.setAliUserId(alipayUserId); aliPaySigningOrder.setSignCode(agreementNo); //处理签约成功的回调 if ("NORMAL".equals(status)) { //修改订单状态为成功 aliPaySigningOrder.setStatus(1); //aliPaySigningOrderService.update(new AliPaySigningOrderEntity(), updateWrapper); AliPayInOrderByAgreementReq payInOrderByAgreementReq = new AliPayInOrderByAgreementReq(); payInOrderByAgreementReq.setAuthCode(agreementNo); payInOrderByAgreementReq.setSubject("会员随心选"); String price = "19.9"; payInOrderByAgreementReq.setTotalAmount(price); String outTradeNo = OrderUtil.getOutTradeNo(); //保存支付的订单号 aliPaySigningOrder.setOtherOrderId(outTradeNo); payInOrderByAgreementReq.setOutTradeNo(outTradeNo); aliPaySigningOrder.setStatus(1); //设置下次续费的时间 aliPaySigningOrder.setNextPayTime(LocalDateTime.now().plusDays(31)); log.info("支付宝签约修改成功订单"+aliPaySigningOrder+"================================"); boolean b = aliPaySigningOrderService.updateById(aliPaySigningOrder); log.info("支付宝签约修改结果:=========================================================="+b); //进行扣款 aliPayService.aliPayTradePayByAgreement(payInOrderByAgreementReq,aliPaySigningOrder); }else { //修改订单状态为失败 aliPaySigningOrder.setStatus(0); aliPaySigningOrderService.updateById(aliPaySigningOrder); } } return "success"; } catch (AlipayApiException e) { //log.info("支付宝签约回调:处理过程异常,error:{}",e.getMessage()); } return "fail"; } /** * 代扣支付回调 * { * "gmt_create":"2023-05-22 18:04:31", * "charset":"UTF-8", * "seller_email":"heyuwangluo2020@163.com", * "subject":"测试扣款", * "sign":"sTtiNS55mONsj2w54+llyqhmDjW9VsxqzI6omvbS6WaWLsCz4yTUMqebESl/S1q9IWsC3o1iJnG/fSax/YXtSldNAzKAKeTU/2zzcGp4o/9nUu9kKIRR92H51otgjK6ja5/4vfAwZ96LwnaJn0BWVYx0YE7kHtGtd84MsvVJ+rGEuWv8TsWJEjey3bcKQRPE3TJwuflwZbfG7Com+U+6H2zQ93O351To0H/oqG3exAXGBdbv5Tw2Rc63Jg4rospSw3f8qUSNq+B8nXcUKfto5RMgehg4yA9GlyzXPmC4eDLDPQ+qsTCja9sWVbz70rVsme4M9V2SB8vEozPKCK6mIQ==", * "buyer_id":"2088722249554680", * "invoice_amount":"0.01", * "notify_id":"2023052201222180433054681491186225", * "fund_bill_list":"[{\"amount\":\"0.01\",\"fundChannel\":\"ALIPAYACCOUNT\"}]", * "notify_type":"trade_status_sync", * "trade_status":"TRADE_SUCCESS", * "receipt_amount":"0.01", * "app_id":"2021003127667792", * "buyer_pay_amount":"0.01", * "sign_type":"RSA2", * "seller_id":"2088441130447941", * "gmt_payment":"2023-05-22 18:04:32", * "notify_time":"2023-05-22 18:07:19", * "version":"1.0", * "out_trade_no":"Y2023052218043074501000", * "total_amount":"0.01", * "trade_no":"2023052222001454681455191308", * "auth_app_id":"2021003127667792", * "buyer_//logon_id":"151****4506", * "point_amount":"0.00" * } * * @param inMap * @return */ @ApiOperation(value = "ces", notes = "cs") @PostMapping("/ces") public String agreementNotify(@RequestBody Map inMap) { log.info("支付宝代扣回调开始:request{}"+JSON.toJSONString(inMap)); try { //验签 boolean signVerified = AlipaySignature.certVerifyV1(inMap, certAlipayRequest.getAlipayPublicCertPath(), AlipayConstants.CHARSET_UTF8, AlipayConstants.SIGN_TYPE_RSA2); if (signVerified) { //支付宝交易号。支付宝交易凭证号。 String tradeNo = inMap.get("trade_no"); //商户订单号 String outTradeNo = inMap.get("out_trade_no"); //卖家支付宝账号。 String sellerEmail = inMap.get("seller_email"); //订单标题。商品的标题/交易标题/订单标题/订单关键字等,是请求时对应的参数,原样通知回来。 String subject = inMap.get("subject"); //买家支付宝用户号。买家支付宝账号对应的支付宝唯一用户号。 String buyerId = inMap.get("buyer_id"); //开票金额。用户在交易中支付的可开发票的金额。支持小数点后两位。 String invoiceAmount = inMap.get("invoice_amount"); //支付金额信息。支付成功的各个渠道金额信息,详请可查看下表 资金明细信息说明 。 String fundBillList = inMap.get("fund_bill_list"); //通知类型。枚举值:trade_status_sync。 String notifyType = inMap.get("notify_type"); //交易状态。咨询目前所处的状态。 TRADE_CLOSED String tradeStatus = inMap.get("trade_status"); //实收金额。商家在交易中实际收到的款项,单位为人民币(元)。支持小数点后两位。 String receiptAmount = inMap.get("receipt_amount"); //开发者的 app_id。支付宝分配给开发者的应用 APPID。 String appId = inMap.get("app_id"); //付款金额。用户在咨询中支付的金额。支持小数点后两位。 String buyerPayAmount = inMap.get("buyer_pay_amount"); //卖家支付宝用户号。 String sellerId = inMap.get("seller_id"); //订单金额。本次交易支付的订单金额,单位为人民币(元)。支持小数点后两位。 String totalAmount = inMap.get("total_amount"); //交易创建时间。该笔交易创建的时间。格式 为 yyyy-MM-dd HH:mm:ss。 String gmtCreate = inMap.get("gmt_create"); //交易 付款时间。该笔交易的买家付款时间。格式为 yyyy-MM-dd HH:mm:ss。 String gmtPayment = inMap.get("gmt_payment"); //通知时间。通知的发送时间。格式为 yyyy-MM-dd HH:mm:ss。 String notifyTime = inMap.get("notify_time"); log.info("支付宝支付回调:" + inMap.toString()); log.info("outTradeNo====================="+outTradeNo); AliPaySigningOrderEntity aliPaySigningOrderEntity = aliPaySigningOrderService.getOne(new QueryWrapper().eq("other_order_id", outTradeNo)); // for (AliPayOrderEntity aliPayOrderEntity : aliPayOrderService.list(new QueryWrapper<>())) { // System.out.println(aliPayOrderEntity); // } if (aliPaySigningOrderEntity==null){ log.info("未查询到订单"); return "success"; } AliPayOrderEntity aliPayOrderEntity = new AliPayOrderEntity(); aliPayOrderEntity.setOrderId(System.currentTimeMillis()+""); aliPayOrderEntity.setOrderTime(LocalDateTime.now()); aliPayOrderEntity.setPrice(aliPaySigningOrderEntity.getPrice()); aliPayOrderEntity.setIsPage(aliPaySigningOrderEntity.getIsPage()); aliPayOrderEntity.setAliUserId(aliPaySigningOrderEntity.getAliUserId()); aliPayOrderEntity.setOtherOrderId(aliPaySigningOrderEntity.getOtherOrderId()); aliPayOrderEntity.setMobile(aliPaySigningOrderEntity.getMobile()); aliPayOrderEntity.setSignCode(aliPaySigningOrderEntity.getSignCode()); aliPayOrderEntity.setBusinessType(aliPaySigningOrderEntity.getBusinessType()); aliPayOrderEntity.setLinkId(aliPaySigningOrderEntity.getLinkId()); aliPayOrderEntity.setLinkName(aliPaySigningOrderEntity.getLinkName()); aliPayOrderEntity.setOrderName("会员随心选"); if ("TRADE_SUCCESS".equals(tradeStatus) || "TRADE_FINISHED".equals(tradeStatus)) { // TODO: 2023/05/22 1.处理业务 aliPayOrderEntity.setStatus(1); aliPayOrderService.save(aliPayOrderEntity); log.info("支付订单保存成功"+aliPayOrderEntity); // if (b){ // log.info("支付订单保存成功"+aliPayEntity.getOrderId()+"=====status:"+aliPayEntity.getStatus()); // // } return "success"; } aliPayOrderEntity.setStatus(0); aliPayOrderService.save(aliPayOrderEntity); log.info("支付开通失败订单保存成功"+aliPayOrderEntity); } } catch (AlipayApiException e) { log.info("支付宝代扣支付回调:处理过程异常,error:{}" + e.getMessage()); } return "fail"; } private int checkFrom(String mobile) { mobile = mobile.substring(0, 3); List uniList = Arrays.asList(unicom); List mobileList = Arrays.asList(mobileArray); List telList = Arrays.asList(tel); int operatorsId = 0; if (mobileList.contains(mobile)) { operatorsId = 1; } else if (uniList.contains(mobile)) { operatorsId = 2; } else if (telList.contains(mobile)) { operatorsId = 3; } else { operatorsId = 0; } return operatorsId; } }