diff --git a/pom.xml b/pom.xml index 70286b1..9adeb51 100644 --- a/pom.xml +++ b/pom.xml @@ -39,6 +39,7 @@ 1.6.2 1.6.3 1.6.2 + 2.9.11 3.8.1 ${env.NACOS_SERVER_NAME} ${env.NACOS_SERVER_PORT} @@ -335,6 +336,13 @@ javax.mail ${mail.version} + + + + com.github.javen205 + IJPay-All + ${ijapy.version} + diff --git a/wfc-api/wfc-api-user/src/main/java/org/wfc/user/api/RemoteUUserService.java b/wfc-api/wfc-api-user/src/main/java/org/wfc/user/api/RemoteUUserService.java index 039f634..80aff8a 100644 --- a/wfc-api/wfc-api-user/src/main/java/org/wfc/user/api/RemoteUUserService.java +++ b/wfc-api/wfc-api-user/src/main/java/org/wfc/user/api/RemoteUUserService.java @@ -15,6 +15,7 @@ import org.wfc.common.core.domain.R; import org.wfc.common.core.web.page.TableDataInfo; import org.wfc.user.api.domain.UUser; import org.wfc.user.api.domain.bo.UClientBo; +import org.wfc.user.api.domain.vo.UOrderVo; import org.wfc.user.api.factory.RemoteUUserFallbackFactory; /** @@ -84,4 +85,10 @@ public interface RemoteUUserService */ @PostMapping("/client/recordClientUser") public R recordClientUser(@RequestBody UClientBo clientBo); + + @PostMapping("/order/paySuccess/{id}") + public R paySuccess(@PathVariable("id") Long id, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); + + @GetMapping(value = "/order/{id}") + public R getOrderById(@PathVariable("id") Long id); } diff --git a/wfc-api/wfc-api-user/src/main/java/org/wfc/user/api/domain/vo/UOrderVo.java b/wfc-api/wfc-api-user/src/main/java/org/wfc/user/api/domain/vo/UOrderVo.java new file mode 100644 index 0000000..a2e9a74 --- /dev/null +++ b/wfc-api/wfc-api-user/src/main/java/org/wfc/user/api/domain/vo/UOrderVo.java @@ -0,0 +1,40 @@ +package org.wfc.user.api.domain.vo; + +import lombok.Data; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * @author: cyc + * @since: 2025-01-13 + */ +@Data +public class UOrderVo { + + private Long userId; + + private Long packageId; + + private Long paymentId; + + private String orderNo; + + private Integer type; + + private BigDecimal orderAmount; + + private Integer status; + + private Long id; + + private Boolean delFlag; + + private Long createBy; + + private Date createTime; + + private Long updateBy; + + private Date updateTime; +} diff --git a/wfc-api/wfc-api-user/src/main/java/org/wfc/user/api/factory/RemoteUUserFallbackFactory.java b/wfc-api/wfc-api-user/src/main/java/org/wfc/user/api/factory/RemoteUUserFallbackFactory.java index d77f0bc..010682d 100644 --- a/wfc-api/wfc-api-user/src/main/java/org/wfc/user/api/factory/RemoteUUserFallbackFactory.java +++ b/wfc-api/wfc-api-user/src/main/java/org/wfc/user/api/factory/RemoteUUserFallbackFactory.java @@ -11,6 +11,7 @@ import org.wfc.common.core.web.page.TableDataInfo; import org.wfc.user.api.RemoteUUserService; import org.wfc.user.api.domain.UUser; import org.wfc.user.api.domain.bo.UClientBo; +import org.wfc.user.api.domain.vo.UOrderVo; import java.util.Collections; @@ -71,6 +72,16 @@ public class RemoteUUserFallbackFactory implements FallbackFactory recordClientUser(UClientBo clientBo) { return R.fail("根据设备mac保存或更新设备信息失败:" + throwable.getMessage()); } + + @Override + public R paySuccess(Long id, String source) { + return R.fail("pay callback error:" + throwable.getMessage()); + } + + @Override + public R getOrderById(Long id) { + return R.fail("get order error:" + throwable.getMessage()); + } }; } } diff --git a/wfc-modules/wfc-payment/pom.xml b/wfc-modules/wfc-payment/pom.xml index f799cb9..4e2f363 100644 --- a/wfc-modules/wfc-payment/pom.xml +++ b/wfc-modules/wfc-payment/pom.xml @@ -73,52 +73,50 @@ wfc-common-swagger - - com.stripe - stripe-java - 20.0.0 + com.github.javen205 + IJPay-WxPay + ${ijapy.version} - - com.github.binarywang - weixin-java-pay - 4.6.0 + com.github.javen205 + IJPay-AliPay + ${ijapy.version} - - com.alipay.sdk - alipay-sdk-java - 4.11.0.ALL + com.github.javen205 + IJPay-QQ + ${ijapy.version} - - com.egzosn - pay-java-union - 2.14.7 + com.github.javen205 + IJPay-UnionPay + ${ijapy.version} - - com.egzosn - pay-java-web-support - 2.14.7 + com.github.javen205 + IJPay-JDPay + ${ijapy.version} - - org.springdoc - springdoc-openapi-ui - 1.6.14 + com.github.javen205 + IJPay-PayPal + ${ijapy.version} + + + + org.wfc + wfc-api-user javax.persistence javax.persistence-api - 2.2 @@ -135,14 +133,7 @@ repackage - - - - - ${wfc-modules-payment.version} - - - + diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/WfcPaymentApplication.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/WfcPaymentApplication.java index 09226d8..c5b3ad7 100644 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/WfcPaymentApplication.java +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/WfcPaymentApplication.java @@ -1,18 +1,11 @@ package org.wfc.payment; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.context.properties.ConfigurationPropertiesScan; -import org.springframework.context.annotation.ComponentScan; -import org.wfc.common.security.annotation.EnableCustomConfig; -import org.wfc.common.security.annotation.EnableRyFeignClients; - -import javax.annotation.PostConstruct; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.wfc.payment.ccpay.config.CcpayConfig; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.wfc.common.security.annotation.EnableCustomConfig; +import org.wfc.common.security.annotation.EnableRyFeignClients; /** * Payment module @@ -26,26 +19,9 @@ public class WfcPaymentApplication { private static final Logger logger = LoggerFactory.getLogger(WfcPaymentApplication.class); - private final CcpayConfig ccpayConfig; - - @Autowired - public WfcPaymentApplication(CcpayConfig ccpayConfig) { - this.ccpayConfig = ccpayConfig; - } - public static void main(String[] args) { SpringApplication.run(WfcPaymentApplication.class, args); logger.info("(♥◠‿◠)ノ゙ Payment module startup successfully ლ(´ڡ`ლ)゙ \n"); } - - @PostConstruct - public void printConfig() { - System.out.println("CCPay PaymentURL: " + ccpayConfig.getPaymentUrl()); - System.out.println("CCPay API Key: " + ccpayConfig.getApiKey()); - System.out.println("CCPay Merchant ID: " + ccpayConfig.getMerchantId()); - System.out.println("CCPay Currency: " + ccpayConfig.getCurrency()); - System.out.println("CCPay Timeout: " + ccpayConfig.getTimeout()); - System.out.println("CCPay Callback URL: " + ccpayConfig.getCallbackUrl()); - } } diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/config/AlipayConfig.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/config/AlipayConfig.java deleted file mode 100644 index 6cb9787..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/config/AlipayConfig.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.wfc.payment.alipay.config; - -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Configuration; - -@Data -@Configuration -@ConfigurationProperties(prefix = "alipay") -public class AlipayConfig { - private String appId; - private String privateKey; - private String publicKey; - private String notifyUrl; - private String returnUrl; - private String signType; - private String charset; - private String gatewayUrl; - private String logPath; - private int maxQueryRetry; - private int queryDuration; - private int maxCancelRetry; - private int cancelDuration; - private int heartbeatDelay; -} \ No newline at end of file diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/controller/AlipayController.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/controller/AlipayController.java deleted file mode 100644 index 9250f47..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/controller/AlipayController.java +++ /dev/null @@ -1,93 +0,0 @@ -package org.wfc.payment.alipay.controller; - -import com.alipay.api.AlipayApiException; -import com.alipay.api.response.AlipayTradeQueryResponse; -import com.alipay.api.response.AlipayTradeCloseResponse; -import com.alipay.api.response.AlipayTradeRefundResponse; - -import java.util.Map; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; -import org.wfc.payment.alipay.service.IAlipayPaymentService; -import org.wfc.payment.alipay.service.IAlipayQueryOrderService; -import org.wfc.payment.alipay.service.IAlipayTradeCloseService; -import org.wfc.payment.alipay.service.IAlipayRefundService; -import org.wfc.payment.alipay.service.IAlipayNotifyService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.AllArgsConstructor; - -@Tag(name = "Ali Pay") -@RestController -@RequestMapping("/alipay") -@AllArgsConstructor -public class AlipayController { - - private final IAlipayPaymentService alipayPaymentService; - private final IAlipayQueryOrderService alipayQueryService; - private final IAlipayTradeCloseService alipayCloseService; - private final IAlipayRefundService alipayRefundService; - - @Operation(summary = "Create Alipay order") - @GetMapping("/pay") - public String pay(@RequestParam String outTradeNo, @RequestParam String totalAmount, @RequestParam String subject, - @RequestParam String body) { - try { - return alipayPaymentService.createPayment(outTradeNo, totalAmount, subject, body); - } catch (AlipayApiException e) { - e.printStackTrace(); - return "Error occurred while processing payment"; - } - } - - @Operation(summary = "Query Alipay order") - @GetMapping("/query") - public AlipayTradeQueryResponse query(@RequestParam String outTradeNo) { - try { - return alipayQueryService.queryOrder(outTradeNo); - } catch (AlipayApiException e) { - e.printStackTrace(); - return null; - } - } - - @Operation(summary = "Close Alipay order") - @GetMapping("/close") - public AlipayTradeCloseResponse close(@RequestParam String outTradeNo) { - try { - return alipayCloseService.closeOrder(outTradeNo); - } catch (AlipayApiException e) { - e.printStackTrace(); - return null; - } - } - - @Operation(summary = "Refund Alipay order") - @GetMapping("/refund") - public AlipayTradeRefundResponse refund(@RequestParam String outTradeNo, @RequestParam String refundAmount, - @RequestParam String refundReason) { - try { - return alipayRefundService.refundOrder(outTradeNo, refundAmount, refundReason); - } catch (AlipayApiException e) { - e.printStackTrace(); - return null; - } - } - - private final IAlipayNotifyService alipayNotifyService; - - @PostMapping("/notify") - public String handleAlipayNotify(@RequestParam Map params) { - try { - boolean result = alipayNotifyService.handleAlipayNotify(params); - return result ? "success" : "failure"; - } catch (AlipayApiException e) { - e.printStackTrace(); - return "failure"; - } - } -} \ No newline at end of file diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/mapper/UAlipayOrderMapper.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/mapper/UAlipayOrderMapper.java deleted file mode 100644 index 8509f4a..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/mapper/UAlipayOrderMapper.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.wfc.payment.alipay.mapper; - -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.wfc.payment.alipay.model.UAlipayOrderModel; - -@Mapper -public interface UAlipayOrderMapper { - - void insertOrder(UAlipayOrderModel uAlipayOrder); - - void updateOrder(UAlipayOrderModel uAlipayOrder); - - UAlipayOrderModel selectOrderByOutTradeNo(@Param("outTradeNo") String outTradeNo); - - UAlipayOrderModel selectOrderById(@Param("id") Long id); -} \ No newline at end of file diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/model/UAlipayOrderModel.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/model/UAlipayOrderModel.java deleted file mode 100644 index eec103d..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/model/UAlipayOrderModel.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.wfc.payment.alipay.model; - -import javax.persistence.*; -import java.math.BigDecimal; -import java.util.Date; -import lombok.Data; - -@Data -@Entity -public class UAlipayOrderModel { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - private Long userId; - private String outTradeNo; - private String tradeStatus; - private BigDecimal totalAmount; - private String subject; - private String body; - private String createBy; - private Date createTime; - private String updateBy; - private Date updateTime; - - // Getters and Setters -} \ No newline at end of file diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/IAlipayNotifyService.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/IAlipayNotifyService.java deleted file mode 100644 index 4e5bccd..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/IAlipayNotifyService.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.wfc.payment.alipay.service; - -import java.util.Map; - -import com.alipay.api.AlipayApiException; - -public interface IAlipayNotifyService { - boolean handleAlipayNotify(Map params) throws AlipayApiException; -} \ No newline at end of file diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/IAlipayPaymentService.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/IAlipayPaymentService.java deleted file mode 100644 index 825ac63..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/IAlipayPaymentService.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.wfc.payment.alipay.service; - -import com.alipay.api.AlipayApiException; - -public interface IAlipayPaymentService { - String createPayment(String outTradeNo, String totalAmount, String subject, String body) throws AlipayApiException; -} \ No newline at end of file diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/IAlipayQueryOrderService.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/IAlipayQueryOrderService.java deleted file mode 100644 index 8556f76..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/IAlipayQueryOrderService.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.wfc.payment.alipay.service; - -import com.alipay.api.AlipayApiException; -import com.alipay.api.response.AlipayTradeQueryResponse; - -public interface IAlipayQueryOrderService { - AlipayTradeQueryResponse queryOrder(String outTradeNo) throws AlipayApiException; -} \ No newline at end of file diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/IAlipayRefundService.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/IAlipayRefundService.java deleted file mode 100644 index 89c813d..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/IAlipayRefundService.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.wfc.payment.alipay.service; - -import com.alipay.api.AlipayApiException; -import com.alipay.api.response.AlipayTradeRefundResponse; - -public interface IAlipayRefundService { - AlipayTradeRefundResponse refundOrder(String outTradeNo, String refundAmount, String refundReason) - throws AlipayApiException; -} \ No newline at end of file diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/IAlipayTradeCloseService.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/IAlipayTradeCloseService.java deleted file mode 100644 index f59251a..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/IAlipayTradeCloseService.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.wfc.payment.alipay.service; - -import com.alipay.api.AlipayApiException; -import com.alipay.api.response.AlipayTradeCloseResponse; - -public interface IAlipayTradeCloseService { - AlipayTradeCloseResponse closeOrder(String outTradeNo) throws AlipayApiException; -} \ No newline at end of file diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/impl/AlipayNotifyServiceImpl.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/impl/AlipayNotifyServiceImpl.java deleted file mode 100644 index e005dda..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/impl/AlipayNotifyServiceImpl.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.wfc.payment.alipay.service.impl; - -import java.math.BigDecimal; -import java.util.Map; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import org.wfc.payment.alipay.config.AlipayConfig; -import org.wfc.payment.alipay.mapper.UAlipayOrderMapper; -import org.wfc.payment.alipay.model.UAlipayOrderModel; -import org.wfc.payment.alipay.service.IAlipayNotifyService; - -import com.alipay.api.AlipayApiException; -import com.alipay.api.internal.util.AlipaySignature; -import java.util.Date; - -@Service -public class AlipayNotifyServiceImpl implements IAlipayNotifyService { - - private final AlipayConfig alipayConfig; - private final UAlipayOrderMapper alipayOrderMapper; - - @Autowired - public AlipayNotifyServiceImpl(UAlipayOrderMapper alipayOrderMapper, AlipayConfig alipayConfig) { - this.alipayOrderMapper = alipayOrderMapper; - this.alipayConfig = alipayConfig; - } - public boolean handleAlipayNotify(Map params) throws AlipayApiException { - boolean signVerified = AlipaySignature.rsaCheckV1(params, - alipayConfig.getPublicKey(), - alipayConfig.getCharset(), - alipayConfig.getSignType()); - if (signVerified) { - // 处理业务逻辑,例如更新订单状态 - String outTradeNo = params.get("out_trade_no"); - String tradeStatus = params.get("trade_status"); - BigDecimal totalAmount = new BigDecimal(params.get("total_amount")); - String subject = params.get("subject"); - String body = params.get("body"); - - UAlipayOrderModel order = alipayOrderMapper.selectOrderByOutTradeNo(outTradeNo); - if (order == null) { - order = new UAlipayOrderModel(); - order.setOutTradeNo(outTradeNo); - order.setCreateTime(new Date()); - alipayOrderMapper.insertOrder(order); - } - order.setTradeStatus(tradeStatus); - order.setTotalAmount(totalAmount); - order.setSubject(subject); - order.setBody(body); - order.setUpdateTime(new Date()); - - alipayOrderMapper.updateOrder(order); - return "TRADE_SUCCESS".equals(tradeStatus); - } - return false; - } - -} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/impl/AlipayPaymentServiceImpl.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/impl/AlipayPaymentServiceImpl.java deleted file mode 100644 index 9e600cb..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/impl/AlipayPaymentServiceImpl.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.wfc.payment.alipay.service.impl; - -import org.springframework.stereotype.Service; -import com.alipay.api.AlipayApiException; -import com.alipay.api.AlipayClient; -import com.alipay.api.DefaultAlipayClient; -import com.alipay.api.request.AlipayTradePagePayRequest; -import org.wfc.payment.alipay.config.AlipayConfig; -import org.wfc.payment.alipay.service.IAlipayPaymentService; -import lombok.AllArgsConstructor; - -@Service -@AllArgsConstructor -public class AlipayPaymentServiceImpl implements IAlipayPaymentService { - - private final AlipayConfig alipayConfig; - - @Override - public String createPayment(String outTradeNo, String totalAmount, String subject, String body) - throws AlipayApiException { - AlipayClient alipayClient = new DefaultAlipayClient( - alipayConfig.getGatewayUrl(), - alipayConfig.getAppId(), - alipayConfig.getPrivateKey(), - "json", - alipayConfig.getCharset(), - alipayConfig.getPublicKey(), - alipayConfig.getSignType()); - - AlipayTradePagePayRequest request = new AlipayTradePagePayRequest(); - request.setReturnUrl(alipayConfig.getReturnUrl()); - request.setNotifyUrl(alipayConfig.getNotifyUrl()); - - request.setBizContent("{" + - "\"out_trade_no\":\"" + outTradeNo + "\"," + - "\"total_amount\":\"" + totalAmount + "\"," + - "\"subject\":\"" + subject + "\"," + - "\"body\":\"" + body + "\"," + - "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"" + - "}"); - - return alipayClient.pageExecute(request).getBody(); - } -} \ No newline at end of file diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/impl/AlipayQueryOrderServiceImpl.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/impl/AlipayQueryOrderServiceImpl.java deleted file mode 100644 index 3445708..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/impl/AlipayQueryOrderServiceImpl.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.wfc.payment.alipay.service.impl; - -import org.springframework.stereotype.Service; -import com.alipay.api.AlipayApiException; -import com.alipay.api.AlipayClient; -import com.alipay.api.DefaultAlipayClient; -import com.alipay.api.request.AlipayTradeQueryRequest; -import com.alipay.api.response.AlipayTradeQueryResponse; - -import lombok.AllArgsConstructor; - -import org.wfc.payment.alipay.config.AlipayConfig; -import org.wfc.payment.alipay.service.IAlipayQueryOrderService; - -@Service -@AllArgsConstructor -public class AlipayQueryOrderServiceImpl implements IAlipayQueryOrderService { - - private final AlipayConfig alipayConfig; - - @Override - public AlipayTradeQueryResponse queryOrder(String outTradeNo) throws AlipayApiException { - AlipayClient alipayClient = new DefaultAlipayClient( - alipayConfig.getGatewayUrl(), - alipayConfig.getAppId(), - alipayConfig.getPrivateKey(), - "json", - alipayConfig.getCharset(), - alipayConfig.getPublicKey(), - alipayConfig.getSignType()); - - AlipayTradeQueryRequest request = new AlipayTradeQueryRequest(); - request.setBizContent("{" + - "\"out_trade_no\":\"" + outTradeNo + "\"" + - "}"); - - return alipayClient.execute(request); - } -} \ No newline at end of file diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/impl/AlipayRefundServiceImpl.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/impl/AlipayRefundServiceImpl.java deleted file mode 100644 index 1911be1..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/impl/AlipayRefundServiceImpl.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.wfc.payment.alipay.service.impl; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; -import com.alipay.api.AlipayApiException; -import com.alipay.api.AlipayClient; -import com.alipay.api.DefaultAlipayClient; -import com.alipay.api.request.AlipayTradeRefundRequest; -import com.alipay.api.response.AlipayTradeRefundResponse; - -import lombok.AllArgsConstructor; - -import org.wfc.payment.alipay.config.AlipayConfig; -import org.wfc.payment.alipay.service.IAlipayRefundService; - -@Service -@AllArgsConstructor -public class AlipayRefundServiceImpl implements IAlipayRefundService { - - private final AlipayConfig alipayConfig; - - @Override - public AlipayTradeRefundResponse refundOrder(String outTradeNo, String refundAmount, String refundReason) - throws AlipayApiException { - AlipayClient alipayClient = new DefaultAlipayClient( - alipayConfig.getGatewayUrl(), - alipayConfig.getAppId(), - alipayConfig.getPrivateKey(), - "json", - alipayConfig.getCharset(), - alipayConfig.getPublicKey(), - alipayConfig.getSignType()); - - AlipayTradeRefundRequest request = new AlipayTradeRefundRequest(); - request.setBizContent("{" + - "\"out_trade_no\":\"" + outTradeNo + "\"," + - "\"refund_amount\":\"" + refundAmount + "\"," + - "\"refund_reason\":\"" + refundReason + "\"" + - "}"); - - return alipayClient.execute(request); - } -} \ No newline at end of file diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/impl/AlipayTradeCloseServiceImpl.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/impl/AlipayTradeCloseServiceImpl.java deleted file mode 100644 index 7ace275..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/alipay/service/impl/AlipayTradeCloseServiceImpl.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.wfc.payment.alipay.service.impl; - -import org.springframework.stereotype.Service; -import com.alipay.api.AlipayApiException; -import com.alipay.api.AlipayClient; -import com.alipay.api.DefaultAlipayClient; -import com.alipay.api.request.AlipayTradeCloseRequest; -import com.alipay.api.response.AlipayTradeCloseResponse; -import org.wfc.payment.alipay.config.AlipayConfig; -import org.wfc.payment.alipay.service.IAlipayTradeCloseService; -import lombok.AllArgsConstructor; - -@Service -@AllArgsConstructor -public class AlipayTradeCloseServiceImpl implements IAlipayTradeCloseService { - - private final AlipayConfig alipayConfig; - - @Override - public AlipayTradeCloseResponse closeOrder(String outTradeNo) throws AlipayApiException { - AlipayClient alipayClient = new DefaultAlipayClient( - alipayConfig.getGatewayUrl(), - alipayConfig.getAppId(), - alipayConfig.getPrivateKey(), - "json", - alipayConfig.getCharset(), - alipayConfig.getPublicKey(), - alipayConfig.getSignType()); - - AlipayTradeCloseRequest request = new AlipayTradeCloseRequest(); - request.setBizContent("{" + - "\"out_trade_no\":\"" + outTradeNo + "\"" + - "}"); - - return alipayClient.execute(request); - } -} \ No newline at end of file diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/service/IUCreditCardTokenService.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/service/IUCreditCardTokenService.java deleted file mode 100644 index 98b2432..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/service/IUCreditCardTokenService.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.wfc.payment.ccpay.service; - -import org.wfc.payment.ccpay.model.PaymentRequest; -import org.wfc.payment.ccpay.model.UCreditCardToken; - -public interface IUCreditCardTokenService { - - void saveToken(UCreditCardToken token); - - UCreditCardToken getTokenByUserId(Long userId); - - String getPaymentToken(PaymentRequest paymentRequest); -} \ No newline at end of file diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/config/PayConfigurer.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/config/PayConfigurer.java new file mode 100644 index 0000000..7149532 --- /dev/null +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/config/PayConfigurer.java @@ -0,0 +1,16 @@ +package org.wfc.payment.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.wfc.payment.interceptor.AliPayInterceptor; +import org.wfc.payment.interceptor.WxPayInterceptor; + +@Configuration +public class PayConfigurer implements WebMvcConfigurer { + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(new AliPayInterceptor()).addPathPatterns("/aliPay/**"); + registry.addInterceptor(new WxPayInterceptor()).addPathPatterns("/wxPay/**"); + } +} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/domain/AliPayBean.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/domain/AliPayBean.java new file mode 100644 index 0000000..b418a43 --- /dev/null +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/domain/AliPayBean.java @@ -0,0 +1,27 @@ +package org.wfc.payment.domain; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * + *

支付宝配置 Bean

+ * + * @author cyc + */ +@Component +@Data +@ConfigurationProperties(prefix = "alipay") +public class AliPayBean { + private String appId; + private String privateKey; + private String publicKey; + private String appCertPath; + private String aliPayCertPath; + private String aliPayRootCertPath; + private String serverUrl; + private String domain; + private String testDomain; + +} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/domain/H5SceneInfo.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/domain/H5SceneInfo.java new file mode 100644 index 0000000..4496902 --- /dev/null +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/domain/H5SceneInfo.java @@ -0,0 +1,82 @@ +package org.wfc.payment.domain; + +import com.alibaba.fastjson.JSON; + +/** + * @author cyc + */ +public class H5SceneInfo { + private H5 h5_info; + + public H5 getH5Info() { + return h5_info; + } + + public void setH5Info(H5 h5_info) { + this.h5_info = h5_info; + } + + + @Override + public String toString() { + return JSON.toJSONString(this); + } + + + public static class H5 { + private String type; + private String app_name; + private String bundle_id; + private String package_name; + private String wap_url; + private String wap_name; + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getApp_name() { + return app_name; + } + + public void setApp_name(String app_name) { + this.app_name = app_name; + } + + public String getBundle_id() { + return bundle_id; + } + + public void setBundle_id(String bundle_id) { + this.bundle_id = bundle_id; + } + + public String getPackage_name() { + return package_name; + } + + public void setPackage_name(String package_name) { + this.package_name = package_name; + } + + public String getWap_url() { + return wap_url; + } + + public void setWap_url(String wap_url) { + this.wap_url = wap_url; + } + + public String getWap_name() { + return wap_name; + } + + public void setWap_name(String wap_name) { + this.wap_name = wap_name; + } + } +} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/domain/JdPayBean.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/domain/JdPayBean.java new file mode 100644 index 0000000..8a430e8 --- /dev/null +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/domain/JdPayBean.java @@ -0,0 +1,71 @@ +package org.wfc.payment.domain; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * + *

JD配置 Bean

+ * + * @author cyc + */ +@Component +@ConfigurationProperties(prefix = "jdpay") +public class JdPayBean { + private String mchId; + private String rsaPrivateKey; + private String desKey; + private String rsaPublicKey; + private String certPath; + + public String getMchId() { + return mchId; + } + + public void setMchId(String mchId) { + this.mchId = mchId; + } + + public String getRsaPrivateKey() { + return rsaPrivateKey; + } + + public void setRsaPrivateKey(String rsaPrivateKey) { + this.rsaPrivateKey = rsaPrivateKey; + } + + public String getDesKey() { + return desKey; + } + + public void setDesKey(String desKey) { + this.desKey = desKey; + } + + public String getRsaPublicKey() { + return rsaPublicKey; + } + + public void setRsaPublicKey(String rsaPublicKey) { + this.rsaPublicKey = rsaPublicKey; + } + + public String getCertPath() { + return certPath; + } + + public void setCertPath(String certPath) { + this.certPath = certPath; + } + + @Override + public String toString() { + return "JdPayBean{" + + "mchId='" + mchId + '\'' + + ", rsaPrivateKey='" + rsaPrivateKey + '\'' + + ", desKey='" + desKey + '\'' + + ", rsaPublicKey='" + rsaPublicKey + '\'' + + ", certPath='" + certPath + '\'' + + '}'; + } +} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/domain/PayPalBean.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/domain/PayPalBean.java new file mode 100644 index 0000000..4857cea --- /dev/null +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/domain/PayPalBean.java @@ -0,0 +1,61 @@ +package org.wfc.payment.domain; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * + *

PayPal配置 Bean

+ * + * @author cyc + */ +@Component +@ConfigurationProperties(prefix = "paypal") +public class PayPalBean { + private String clientId; + private String secret; + private Boolean sandBox; + private String domain; + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public String getSecret() { + return secret; + } + + public void setSecret(String secret) { + this.secret = secret; + } + + public Boolean getSandBox() { + return sandBox; + } + + public void setSandBox(Boolean sandBox) { + this.sandBox = sandBox; + } + + public String getDomain() { + return domain; + } + + public void setDomain(String domain) { + this.domain = domain; + } + + @Override + public String toString() { + return "PayPalBean{" + + "clientId='" + clientId + '\'' + + ", secret='" + secret + '\'' + + ", sandBox=" + sandBox + + ", domain='" + domain + '\'' + + '}'; + } +} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/domain/UnionPayBean.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/domain/UnionPayBean.java new file mode 100644 index 0000000..60501d1 --- /dev/null +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/domain/UnionPayBean.java @@ -0,0 +1,61 @@ +package org.wfc.payment.domain; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * + *

云闪付配置 Bean

+ * + * @author cyc + */ +@Component +@ConfigurationProperties(prefix = "union") +public class UnionPayBean { + private String machId; + private String key; + private String serverUrl; + private String domain; + + public String getMachId() { + return machId; + } + + public void setMachId(String machId) { + this.machId = machId; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getServerUrl() { + return serverUrl; + } + + public void setServerUrl(String serverUrl) { + this.serverUrl = serverUrl; + } + + public String getDomain() { + return domain; + } + + public void setDomain(String domain) { + this.domain = domain; + } + + @Override + public String toString() { + return "UnionPayBean{" + + "machId='" + machId + '\'' + + ", key='" + key + '\'' + + ", serverUrl='" + serverUrl + '\'' + + ", domain='" + domain + '\'' + + '}'; + } +} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/domain/WxPayBean.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/domain/WxPayBean.java new file mode 100644 index 0000000..ab7d9e5 --- /dev/null +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/domain/WxPayBean.java @@ -0,0 +1,75 @@ +package org.wfc.payment.domain; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * + *

微信配置 Bean

+ * + * @author cyc + */ +@Component +@ConfigurationProperties(prefix = "wxpay") +public class WxPayBean { + private String appId; + private String appSecret; + private String mchId; + private String partnerKey; + private String certPath; + private String domain; + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public String getAppSecret() { + return appSecret; + } + + public void setAppSecret(String appSecret) { + this.appSecret = appSecret; + } + + public String getMchId() { + return mchId; + } + + public void setMchId(String mchId) { + this.mchId = mchId; + } + + public String getPartnerKey() { + return partnerKey; + } + + public void setPartnerKey(String partnerKey) { + this.partnerKey = partnerKey; + } + + public String getCertPath() { + return certPath; + } + + public void setCertPath(String certPath) { + this.certPath = certPath; + } + + public String getDomain() { + return domain; + } + + public void setDomain(String domain) { + this.domain = domain; + } + + @Override + public String toString() { + return "WxPayBean [appId=" + appId + ", appSecret=" + appSecret + ", mchId=" + mchId + ", partnerKey=" + + partnerKey + ", certPath=" + certPath + ", domain=" + domain + "]"; + } +} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/domain/WxPayV3Bean.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/domain/WxPayV3Bean.java new file mode 100644 index 0000000..a1dc1cb --- /dev/null +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/domain/WxPayV3Bean.java @@ -0,0 +1,119 @@ +package org.wfc.payment.domain; + +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * + *

微信配置 Bean

+ * + * @author cyc + */ +@Component +@ConfigurationProperties(prefix = "v3") +public class WxPayV3Bean { + private String appId; + private String keyPath; + private String publicKeyPath; + private String certPath; + private String certP12Path; + private String platformCertPath; + private String mchId; + private String apiKey; + private String apiKey3; + private String domain; + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public String getKeyPath() { + return keyPath; + } + + public void setKeyPath(String keyPath) { + this.keyPath = keyPath; + } + + public String getPublicKeyPath() { + return publicKeyPath; + } + + public void setPublicKeyPath(String publicKeyPath) { + this.publicKeyPath = publicKeyPath; + } + + public String getCertPath() { + return certPath; + } + + public void setCertPath(String certPath) { + this.certPath = certPath; + } + + public String getCertP12Path() { + return certP12Path; + } + + public void setCertP12Path(String certP12Path) { + this.certP12Path = certP12Path; + } + + public String getPlatformCertPath() { + return platformCertPath; + } + + public void setPlatformCertPath(String platformCertPath) { + this.platformCertPath = platformCertPath; + } + + public String getMchId() { + return mchId; + } + + public void setMchId(String mchId) { + this.mchId = mchId; + } + + public String getApiKey() { + return apiKey; + } + + public void setApiKey(String apiKey) { + this.apiKey = apiKey; + } + + public String getApiKey3() { + return apiKey3; + } + + public void setApiKey3(String apiKey3) { + this.apiKey3 = apiKey3; + } + + public String getDomain() { + return domain; + } + + public void setDomain(String domain) { + this.domain = domain; + } + + @Override + public String toString() { + return "WxPayV3Bean{" + + "keyPath='" + keyPath + '\'' + + ", certPath='" + certPath + '\'' + + ", certP12Path='" + certP12Path + '\'' + + ", platformCertPath='" + platformCertPath + '\'' + + ", mchId='" + mchId + '\'' + + ", apiKey='" + apiKey + '\'' + + ", apiKey3='" + apiKey3 + '\'' + + ", domain='" + domain + '\'' + + '}'; + } +} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/domain/vo/AjaxResult.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/domain/vo/AjaxResult.java new file mode 100644 index 0000000..b322478 --- /dev/null +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/domain/vo/AjaxResult.java @@ -0,0 +1,85 @@ +package org.wfc.payment.domain.vo; + +import java.io.Serializable; + +/** + * @author cyc + */ +public class AjaxResult implements Serializable { + + private static final long serialVersionUID = 6439646269084700779L; + + private int code = 0; + + /** + * 返回的中文消息 + */ + private String message; + + /** + * 成功时携带的数据 + */ + private Object data; + + public int getCode() { + return code; + } + + public String getMessage() { + return message; + } + + public Object getData() { + return data; + } + + public void setData(Object data) { + this.data = data; + } + + /** + * 校验错误 + * + * @return + */ + public boolean hasError() { + return this.code != 0; + } + + /** + * 添加错误,用于alertError + * + * @param message + * @return + */ + public AjaxResult addError(String message) { + this.message = message; + this.code = 1; + return this; + } + + /** + * 用于Confirm的错误信息 + * + * @param message 描述消息 + * @return {AjaxResult} + */ + public AjaxResult addConfirmError(String message) { + this.message = message; + this.code = 2; + return this; + } + + /** + * 封装成功时的数据 + * + * @param data Object + * @return {AjaxResult} + */ + public AjaxResult success(Object data) { + this.data = data; + this.code = 0; + return this; + } + +} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/interceptor/AliPayInterceptor.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/interceptor/AliPayInterceptor.java new file mode 100644 index 0000000..84b987b --- /dev/null +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/interceptor/AliPayInterceptor.java @@ -0,0 +1,33 @@ +package org.wfc.payment.interceptor; + +import com.alipay.api.AlipayApiException; +import com.ijpay.alipay.AliPayApiConfigKit; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; +import org.wfc.payment.pay.alipay.controller.AbstractAliPayApiController; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * + *

支付宝支付拦截器

+ * + * @author cyc + */ +public class AliPayInterceptor implements HandlerInterceptor { + + @Override + public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws AlipayApiException { + if (HandlerMethod.class.equals(handler.getClass())) { + HandlerMethod method = (HandlerMethod) handler; + Object controller = method.getBean(); + if (!(controller instanceof AbstractAliPayApiController)) { + throw new RuntimeException("Controller need to inherit AbstractAliPayApiController"); + } + AliPayApiConfigKit.setThreadLocalAliPayApiConfig(((AbstractAliPayApiController) controller).getApiConfig()); + return true; + } + return false; + } +} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/interceptor/WxPayInterceptor.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/interceptor/WxPayInterceptor.java new file mode 100644 index 0000000..2151caf --- /dev/null +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/interceptor/WxPayInterceptor.java @@ -0,0 +1,32 @@ +package org.wfc.payment.interceptor; + +import com.ijpay.wxpay.WxPayApiConfigKit; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; +import org.wfc.payment.pay.wxpay.controller.AbstractWxPayApiController; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * + *

微信支付拦截器

+ * + * @author cyc + */ +public class WxPayInterceptor implements HandlerInterceptor { + + @Override + public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) { + if (HandlerMethod.class.equals(handler.getClass())) { + HandlerMethod method = (HandlerMethod) handler; + Object controller = method.getBean(); + if (!(controller instanceof AbstractWxPayApiController)) { + throw new RuntimeException("Controller need to inherit AbstractWxPayApiController"); + } + WxPayApiConfigKit.setThreadLocalWxPayApiConfig(((AbstractWxPayApiController) controller).getApiConfig()); + return true; + } + return false; + } +} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/alipay/controller/AbstractAliPayApiController.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/alipay/controller/AbstractAliPayApiController.java new file mode 100644 index 0000000..1043163 --- /dev/null +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/alipay/controller/AbstractAliPayApiController.java @@ -0,0 +1,17 @@ +package org.wfc.payment.pay.alipay.controller; + +import com.alipay.api.AlipayApiException; +import com.ijpay.alipay.AliPayApiConfig; + +/** + * @author cyc + */ +public abstract class AbstractAliPayApiController { + /** + * 获取支付宝配置 + * + * @return {@link AliPayApiConfig} 支付宝配置 + * @throws AlipayApiException 支付宝 Api 异常 + */ + public abstract AliPayApiConfig getApiConfig() throws AlipayApiException; +} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/alipay/controller/AliPayController.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/alipay/controller/AliPayController.java new file mode 100644 index 0000000..4bb426f --- /dev/null +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/alipay/controller/AliPayController.java @@ -0,0 +1,823 @@ +package org.wfc.payment.pay.alipay.controller; + +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSONObject; +import com.alipay.api.AlipayApiException; +import com.alipay.api.domain.AlipayCommerceCityfacilitatorVoucherGenerateModel; +import com.alipay.api.domain.AlipayDataDataserviceBillDownloadurlQueryModel; +import com.alipay.api.domain.AlipayFundAccountQueryModel; +import com.alipay.api.domain.AlipayFundAuthOrderFreezeModel; +import com.alipay.api.domain.AlipayFundCouponOrderAgreementPayModel; +import com.alipay.api.domain.AlipayFundTransCommonQueryModel; +import com.alipay.api.domain.AlipayFundTransOrderQueryModel; +import com.alipay.api.domain.AlipayFundTransToaccountTransferModel; +import com.alipay.api.domain.AlipayFundTransUniTransferModel; +import com.alipay.api.domain.AlipayOpenAuthTokenAppModel; +import com.alipay.api.domain.AlipayOpenAuthTokenAppQueryModel; +import com.alipay.api.domain.AlipayTradeAppPayModel; +import com.alipay.api.domain.AlipayTradeCancelModel; +import com.alipay.api.domain.AlipayTradeCloseModel; +import com.alipay.api.domain.AlipayTradeCreateModel; +import com.alipay.api.domain.AlipayTradeOrderSettleModel; +import com.alipay.api.domain.AlipayTradePagePayModel; +import com.alipay.api.domain.AlipayTradePayModel; +import com.alipay.api.domain.AlipayTradePrecreateModel; +import com.alipay.api.domain.AlipayTradeQueryModel; +import com.alipay.api.domain.AlipayTradeRefundModel; +import com.alipay.api.domain.AlipayTradeWapPayModel; +import com.alipay.api.domain.Participant; +import com.alipay.api.internal.util.AlipaySignature; +import com.alipay.api.response.AlipayFundAuthOrderFreezeResponse; +import com.alipay.api.response.AlipayFundCouponOrderAgreementPayResponse; +import com.alipay.api.response.AlipayTradeCreateResponse; +import com.ijpay.alipay.AliPayApi; +import com.ijpay.alipay.AliPayApiConfig; +import com.ijpay.alipay.AliPayApiConfigKit; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.wfc.common.core.domain.R; +import org.wfc.payment.domain.AliPayBean; +import org.wfc.payment.utils.StringUtils; +import org.wfc.payment.domain.vo.AjaxResult; +import org.wfc.user.api.RemoteUUserService; +import org.wfc.user.api.domain.vo.UOrderVo; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.math.RoundingMode; +import java.util.HashMap; +import java.util.Map; + +/** + * + *

支付宝支付 Demo

+ * + * @author cyc + */ +@Controller +@RequestMapping("/aliPay") +public class AliPayController extends AbstractAliPayApiController { + private static final Logger log = LoggerFactory.getLogger(AliPayController.class); + + @Resource + private AliPayBean aliPayBean; + + @Resource + private RemoteUUserService remoteUUserService; + + private final AjaxResult result = new AjaxResult(); + // 普通公钥模式 + private final static String NOTIFY_URL = "/payment/aliPay/callback"; + private final static String PRE_NOTIFY_URL = "/sys-api"; + private final static String TEST_PRE_NOTIFY_URL = "/proxy-default"; + /** + * 证书模式 + */ +// private final static String NOTIFY_URL = "/aliPay/cert_notify_url"; + private final static String RETURN_URL = "/u"; + /** + * 证书模式 + */ +// private final static String RETURN_URL = "/aliPay/cert_return_url"; + + @Override + public AliPayApiConfig getApiConfig() throws AlipayApiException { + AliPayApiConfig aliPayApiConfig; + try { + aliPayApiConfig = AliPayApiConfigKit.getApiConfig(aliPayBean.getAppId()); + } catch (Exception e) { + aliPayApiConfig = AliPayApiConfig.builder() + .setAppId(aliPayBean.getAppId()) + .setAliPayPublicKey(aliPayBean.getPublicKey()) + .setAppCertPath(aliPayBean.getAppCertPath()) + .setAliPayCertPath(aliPayBean.getAliPayCertPath()) + .setAliPayRootCertPath(aliPayBean.getAliPayRootCertPath()) + .setCharset("UTF-8") + .setPrivateKey(aliPayBean.getPrivateKey()) + .setServiceUrl(aliPayBean.getServerUrl()) + .setSignType("RSA2") + // 普通公钥方式 + .build(); + // 证书模式 +// .buildByCert(); + + } + return aliPayApiConfig; + } + + @RequestMapping("/test") + @ResponseBody + public AliPayApiConfig test() { + AliPayApiConfig aliPayApiConfig = AliPayApiConfigKit.getAliPayApiConfig(); + String charset = aliPayApiConfig.getCharset(); + log.info("charset>" + charset); + return aliPayApiConfig; + } + + + /** + * app支付 + */ + @RequestMapping(value = "/appPay") + @ResponseBody + public AjaxResult appPay() { + try { + AlipayTradeAppPayModel model = new AlipayTradeAppPayModel(); + model.setBody("我是测试数据-By Javen"); + model.setSubject("App支付测试-By Javen"); + model.setOutTradeNo(StringUtils.getOutTradeNo()); + model.setTimeoutExpress("30m"); + model.setTotalAmount("0.01"); + model.setPassbackParams("callback params"); + model.setProductCode("QUICK_MSECURITY_PAY"); + String orderInfo = AliPayApi.appPayToResponse(model, aliPayBean.getDomain() + NOTIFY_URL).getBody(); + result.success(orderInfo); + } catch (AlipayApiException e) { + e.printStackTrace(); + result.addError("system error:" + e.getMessage()); + } + return result; + } + + @RequestMapping(value = "/wapPay") + @ResponseBody + public void wapPay(HttpServletResponse response) { + String body = "我是测试数据-By Javen"; + String subject = "Javen Wap支付测试"; + String totalAmount = "1"; + String passBackParams = "1"; + String returnUrl = aliPayBean.getDomain() + RETURN_URL; + String notifyUrl = aliPayBean.getDomain() + NOTIFY_URL; + + AlipayTradeWapPayModel model = new AlipayTradeWapPayModel(); + model.setBody(body); + model.setSubject(subject); + model.setTotalAmount(totalAmount); + model.setPassbackParams(passBackParams); + String outTradeNo = StringUtils.getOutTradeNo(); + System.out.println("wap outTradeNo>" + outTradeNo); + model.setOutTradeNo(outTradeNo); + model.setProductCode("QUICK_WAP_PAY"); + + try { + AliPayApi.wapPay(response, model, returnUrl, notifyUrl); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + /** + * PC支付 + */ + @RequestMapping(value = "/pcPay") + @ResponseBody + public void pcPay(HttpServletResponse response, @RequestParam Long orderId) { + try { + R orderRes = remoteUUserService.getOrderById(orderId); + UOrderVo orderVo = orderRes.getData(); + if (orderVo == null) { + return; + } + String totalAmount = orderVo.getOrderAmount().setScale(2, RoundingMode.HALF_UP).toString(); +// String outTradeNo = StringUtils.getOutTradeNo(); + log.info("pc outTradeNo>" + orderId); + + String returnUrl = aliPayBean.getDomain() + RETURN_URL; + String notifyUrl = aliPayBean.getDomain() + PRE_NOTIFY_URL + NOTIFY_URL; + if (StrUtil.isNotBlank(aliPayBean.getTestDomain())) { + notifyUrl = aliPayBean.getTestDomain() + TEST_PRE_NOTIFY_URL + NOTIFY_URL; + } + AlipayTradePagePayModel model = new AlipayTradePagePayModel(); + + model.setOutTradeNo(orderId.toString()); + model.setProductCode("FAST_INSTANT_TRADE_PAY"); + model.setTotalAmount(totalAmount); + model.setSubject("WANFI PAY"); +// model.setBody("Javen IJPay PC支付测试"); + model.setPassbackParams("passback_params"); + /** + * 花呗分期相关的设置,测试环境不支持花呗分期的测试 + * hb_fq_num代表花呗分期数,仅支持传入3、6、12,其他期数暂不支持,传入会报错; + * hb_fq_seller_percent代表卖家承担收费比例,商家承担手续费传入100,用户承担手续费传入0,仅支持传入100、0两种,其他比例暂不支持,传入会报错。 + */ +// ExtendParams extendParams = new ExtendParams(); +// extendParams.setHbFqNum("3"); +// extendParams.setHbFqSellerPercent("0"); +// model.setExtendParams(extendParams); + + AliPayApi.tradePage(response, model, notifyUrl, returnUrl); + // https://opensupport.alipay.com/support/helpcenter/192/201602488772?ant_source=antsupport + // Alipay Easy SDK(新版)目前只支持输出form表单,不支持打印出url链接。 + // AliPayApi.tradePage(response, "GET", model, notifyUrl, returnUrl); + } catch (Exception e) { + e.printStackTrace(); + } + + } + + @RequestMapping(value = "/tradePay") + @ResponseBody + public String tradePay(@RequestParam("authCode") String authCode, @RequestParam("scene") String scene) { + String subject = null; + String waveCode = "wave_code"; + String barCode = "bar_code"; + if (scene.equals(waveCode)) { + subject = "Javen 支付宝声波支付测试"; + } else if (scene.equals(barCode)) { + subject = "Javen 支付宝条形码支付测试"; + } + String totalAmount = "100"; + String notifyUrl = aliPayBean.getDomain() + NOTIFY_URL; + + AlipayTradePayModel model = new AlipayTradePayModel(); + model.setAuthCode(authCode); + model.setSubject(subject); + model.setTotalAmount(totalAmount); + model.setOutTradeNo(StringUtils.getOutTradeNo()); + model.setScene(scene); + try { + return AliPayApi.tradePayToResponse(model, notifyUrl).getBody(); + } catch (Exception e) { + e.printStackTrace(); + } + + return null; + } + + /** + * 扫码支付 + */ + @RequestMapping(value = "/tradePreCreatePay") + @ResponseBody + public String tradePreCreatePay() { + String subject = "Javen 支付宝扫码支付测试"; + String totalAmount = "86"; + String storeId = "123"; +// String notifyUrl = aliPayBean.getDomain() + NOTIFY_URL; + String notifyUrl = aliPayBean.getDomain() + "/aliPay/cert_notify_url"; + + AlipayTradePrecreateModel model = new AlipayTradePrecreateModel(); + model.setSubject(subject); + model.setTotalAmount(totalAmount); + model.setStoreId(storeId); + model.setTimeoutExpress("5m"); + model.setOutTradeNo(StringUtils.getOutTradeNo()); + try { + String resultStr = AliPayApi.tradePrecreatePayToResponse(model, notifyUrl).getBody(); + JSONObject jsonObject = JSONObject.parseObject(resultStr); + return jsonObject.getJSONObject("alipay_trade_precreate_response").getString("qr_code"); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 单笔转账到支付宝账户 + * https://docs.open.alipay.com/309/106235/ + */ + @RequestMapping(value = "/transfer") + @ResponseBody + public String transfer() { + String totalAmount = "66"; + AlipayFundTransToaccountTransferModel model = new AlipayFundTransToaccountTransferModel(); + model.setOutBizNo(StringUtils.getOutTradeNo()); + model.setPayeeType("ALIPAY_LOGONID"); + model.setPayeeAccount("gxthqd7606@sandbox.com"); + model.setAmount(totalAmount); + model.setPayerShowName("测试退款"); + model.setPayerRealName("沙箱环境"); + model.setRemark("javen测试单笔转账到支付宝"); + + try { + return AliPayApi.transferToResponse(model).getBody(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + @RequestMapping(value = "/transferQuery") + @ResponseBody + public String transferQuery(@RequestParam(required = false, name = "outBizNo") String outBizNo, + @RequestParam(required = false, name = "orderId") String orderId) { + AlipayFundTransOrderQueryModel model = new AlipayFundTransOrderQueryModel(); + if (StringUtils.isNotEmpty(outBizNo)) { + model.setOutBizNo(outBizNo); + } + if (StringUtils.isNotEmpty(orderId)) { + model.setOrderId(orderId); + } + + try { + return AliPayApi.transferQueryToResponse(model).getBody(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + @RequestMapping(value = "/uniTransfer") + @ResponseBody + public String uniTransfer() { + String totalAmount = "1"; + AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel(); + model.setOutBizNo(StringUtils.getOutTradeNo()); + model.setTransAmount(totalAmount); + model.setProductCode("TRANS_ACCOUNT_NO_PWD"); + model.setBizScene("DIRECT_TRANSFER"); + model.setOrderTitle("统一转账-转账至支付宝账户"); + model.setRemark("IJPay 测试统一转账"); + + Participant payeeInfo = new Participant(); + payeeInfo.setIdentity("gxthqd7606@sandbox.com"); + payeeInfo.setIdentityType("ALIPAY_LOGON_ID"); + payeeInfo.setName("沙箱环境"); + model.setPayeeInfo(payeeInfo); + + try { + return AliPayApi.uniTransferToResponse(model, null).getBody(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + @RequestMapping(value = "/uniTransferQuery") + @ResponseBody + public String uniTransferQuery(@RequestParam(required = false, name = "outBizNo") String outBizNo, + @RequestParam(required = false, name = "orderId") String orderId) { + AlipayFundTransCommonQueryModel model = new AlipayFundTransCommonQueryModel(); + if (StringUtils.isNotEmpty(outBizNo)) { + model.setOutBizNo(outBizNo); + } + if (StringUtils.isNotEmpty(orderId)) { + model.setOrderId(orderId); + } + + try { + return AliPayApi.transCommonQueryToResponse(model, null).getBody(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + @RequestMapping(value = "/accountQuery") + @ResponseBody + public String accountQuery(@RequestParam(required = true, name = "aliPayUserId") String aliPayUserId) { + AlipayFundAccountQueryModel model = new AlipayFundAccountQueryModel(); + model.setAlipayUserId(aliPayUserId); + model.setAccountType("ACCTRANS_ACCOUNT"); + try { + return AliPayApi.accountQueryToResponse(model, null).getBody(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 资金授权冻结接口 + */ + @RequestMapping(value = "/authOrderFreeze") + @ResponseBody + public AlipayFundAuthOrderFreezeResponse authOrderFreeze(@RequestParam("auth_code") String authCode) { + try { + AlipayFundAuthOrderFreezeModel model = new AlipayFundAuthOrderFreezeModel(); + model.setOutOrderNo(StringUtils.getOutTradeNo()); + model.setOutRequestNo(StringUtils.getOutTradeNo()); + model.setAuthCode(authCode); + model.setAuthCodeType("bar_code"); + model.setOrderTitle("资金授权冻结-By IJPay"); + model.setAmount("36"); + model.setProductCode("PRE_AUTH"); + + return AliPayApi.authOrderFreezeToResponse(model); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + + /** + * 红包协议支付接口 + * https://docs.open.alipay.com/301/106168/ + */ + @RequestMapping(value = "/agreementPay") + @ResponseBody + public AlipayFundCouponOrderAgreementPayResponse agreementPay() { + try { + AlipayFundCouponOrderAgreementPayModel model = new AlipayFundCouponOrderAgreementPayModel(); + model.setOutOrderNo(StringUtils.getOutTradeNo()); + model.setOutRequestNo(StringUtils.getOutTradeNo()); + model.setOrderTitle("红包协议支付接口-By IJPay"); + model.setAmount("36"); + model.setPayerUserId("2088102180432465"); + + return AliPayApi.fundCouponOrderAgreementPayToResponse(model); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 下载对账单 + */ + @RequestMapping(value = "/dataDataServiceBill") + @ResponseBody + public String dataDataServiceBill(@RequestParam("billDate") String billDate) { + try { + AlipayDataDataserviceBillDownloadurlQueryModel model = new AlipayDataDataserviceBillDownloadurlQueryModel(); + model.setBillType("trade"); + model.setBillDate(billDate); + return AliPayApi.billDownloadUrlQuery(model); + } catch (AlipayApiException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 退款 + */ + @RequestMapping(value = "/tradeRefund") + @ResponseBody + public String tradeRefund(@RequestParam(required = false, name = "outTradeNo") String outTradeNo, @RequestParam(required = false, name = "tradeNo") String tradeNo) { + + try { + AlipayTradeRefundModel model = new AlipayTradeRefundModel(); + if (StringUtils.isNotEmpty(outTradeNo)) { + model.setOutTradeNo(outTradeNo); + } + if (StringUtils.isNotEmpty(tradeNo)) { + model.setTradeNo(tradeNo); + } + model.setRefundAmount("86.00"); + model.setRefundReason("正常退款"); + return AliPayApi.tradeRefundToResponse(model).getBody(); + } catch (AlipayApiException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 交易查询 + */ + @RequestMapping(value = "/tradeQuery") + @ResponseBody + public String tradeQuery(@RequestParam(required = false, name = "outTradeNo") String outTradeNo, @RequestParam(required = false, name = "tradeNo") String tradeNo) { + try { + AlipayTradeQueryModel model = new AlipayTradeQueryModel(); + if (StringUtils.isNotEmpty(outTradeNo)) { + model.setOutTradeNo(outTradeNo); + } + if (StringUtils.isNotEmpty(tradeNo)) { + model.setTradeNo(tradeNo); + } + return AliPayApi.tradeQueryToResponse(model).getBody(); + } catch (AlipayApiException e) { + e.printStackTrace(); + } + return null; + } + + @RequestMapping(value = "/tradeQueryByStr") + @ResponseBody + public String tradeQueryByStr(@RequestParam(required = false, name = "outTradeNo") String outTradeNo, @RequestParam(required = false, name = "tradeNo") String tradeNo) { + AlipayTradeQueryModel model = new AlipayTradeQueryModel(); + if (StringUtils.isNotEmpty(outTradeNo)) { + model.setOutTradeNo(outTradeNo); + } + if (StringUtils.isNotEmpty(tradeNo)) { + model.setTradeNo(tradeNo); + } + + try { + return AliPayApi.tradeQueryToResponse(model).getBody(); + } catch (AlipayApiException e) { + e.printStackTrace(); + } + + return null; + } + + /** + * 创建订单 + * {"alipay_trade_create_response":{"code":"10000","msg":"Success","out_trade_no":"081014283315033","trade_no":"2017081021001004200200274066"},"sign":"ZagfFZntf0loojZzdrBNnHhenhyRrsXwHLBNt1Z/dBbx7cF1o7SZQrzNjRHHmVypHKuCmYifikZIqbNNrFJauSuhT4MQkBJE+YGPDtHqDf4Ajdsv3JEyAM3TR/Xm5gUOpzCY7w+RZzkHevsTd4cjKeGM54GBh0hQH/gSyhs4pEN3lRWopqcKkrkOGZPcmunkbrUAF7+AhKGUpK+AqDw4xmKFuVChDKaRdnhM6/yVsezJFXzlQeVgFjbfiWqULxBXq1gqicntyUxvRygKA+5zDTqE5Jj3XRDjVFIDBeOBAnM+u03fUP489wV5V5apyI449RWeybLg08Wo+jUmeOuXOA=="} + */ + @RequestMapping(value = "/tradeCreate") + @ResponseBody + public String tradeCreate(@RequestParam("outTradeNo") String outTradeNo) { + + String notifyUrl = aliPayBean.getDomain() + NOTIFY_URL; + + AlipayTradeCreateModel model = new AlipayTradeCreateModel(); + model.setOutTradeNo(outTradeNo); + model.setTotalAmount("88.88"); + model.setBody("Body"); + model.setSubject("Javen 测试统一收单交易创建接口"); + //买家支付宝账号,和buyer_id不能同时为空 + model.setBuyerLogonId("abpkvd0206@sandbox.com"); + try { + AlipayTradeCreateResponse response = AliPayApi.tradeCreateToResponse(model, notifyUrl); + return response.getBody(); + } catch (AlipayApiException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 撤销订单 + */ + @RequestMapping(value = "/tradeCancel") + @ResponseBody + public String tradeCancel(@RequestParam(required = false, name = "outTradeNo") String outTradeNo, @RequestParam(required = false, name = "tradeNo") String tradeNo) { + try { + AlipayTradeCancelModel model = new AlipayTradeCancelModel(); + if (StringUtils.isNotEmpty(outTradeNo)) { + model.setOutTradeNo(outTradeNo); + } + if (StringUtils.isNotEmpty(tradeNo)) { + model.setTradeNo(tradeNo); + } + + return AliPayApi.tradeCancelToResponse(model).getBody(); + } catch (AlipayApiException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 关闭订单 + */ + @RequestMapping(value = "/tradeClose") + @ResponseBody + public String tradeClose(@RequestParam("outTradeNo") String outTradeNo, @RequestParam("tradeNo") String tradeNo) { + try { + AlipayTradeCloseModel model = new AlipayTradeCloseModel(); + if (StringUtils.isNotEmpty(outTradeNo)) { + model.setOutTradeNo(outTradeNo); + } + if (StringUtils.isNotEmpty(tradeNo)) { + model.setTradeNo(tradeNo); + } + + return AliPayApi.tradeCloseToResponse(model).getBody(); + } catch (AlipayApiException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 结算 + */ + @RequestMapping(value = "/tradeOrderSettle") + @ResponseBody + public String tradeOrderSettle(@RequestParam("tradeNo") String tradeNo) { + try { + AlipayTradeOrderSettleModel model = new AlipayTradeOrderSettleModel(); + model.setOutRequestNo(StringUtils.getOutTradeNo()); + model.setTradeNo(tradeNo); + + return AliPayApi.tradeOrderSettleToResponse(model).getBody(); + } catch (AlipayApiException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 获取应用授权URL并授权 + */ + @RequestMapping(value = "/toOauth") + @ResponseBody + public void toOauth(HttpServletResponse response) { + try { + String redirectUri = aliPayBean.getDomain() + "/aliPay/redirect_uri"; + String oauth2Url = AliPayApi.getOauth2Url(aliPayBean.getAppId(), redirectUri); + response.sendRedirect(oauth2Url); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 应用授权回调 + */ + @RequestMapping(value = "/redirect_uri") + @ResponseBody + public String redirectUri(@RequestParam("app_id") String appId, @RequestParam("app_auth_code") String appAuthCode) { + try { + System.out.println("app_id:" + appId); + System.out.println("app_auth_code:" + appAuthCode); + //使用app_auth_code换取app_auth_token + AlipayOpenAuthTokenAppModel model = new AlipayOpenAuthTokenAppModel(); + model.setGrantType("authorization_code"); + model.setCode(appAuthCode); + return AliPayApi.openAuthTokenAppToResponse(model).getBody(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 查询授权信息 + */ + @RequestMapping(value = "/openAuthTokenAppQuery") + @ResponseBody + public String openAuthTokenAppQuery(@RequestParam("appAuthToken") String appAuthToken) { + try { + AlipayOpenAuthTokenAppQueryModel model = new AlipayOpenAuthTokenAppQueryModel(); + model.setAppAuthToken(appAuthToken); + return AliPayApi.openAuthTokenAppQueryToResponse(model).getBody(); + } catch (AlipayApiException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 批量付款到支付宝账户有密接口 + */ + @RequestMapping(value = "/batchTrans") + @ResponseBody + public void batchTrans(HttpServletResponse response) { + try { + String signType = "MD5"; + String notifyUrl = aliPayBean.getDomain() + NOTIFY_URL; + Map params = new HashMap<>(15); + params.put("partner", "PID"); + params.put("sign_type", signType); + params.put("notify_url", notifyUrl); + params.put("account_name", "xxx"); + params.put("detail_data", "流水号1^收款方账号1^收款账号姓名1^付款金额1^备注说明1|流水号2^收款方账号2^收款账号姓名2^付款金额2^备注说明2"); + params.put("batch_no", String.valueOf(System.currentTimeMillis())); + params.put("batch_num", 1 + ""); + params.put("batch_fee", 10.00 + ""); + params.put("email", "xx@xxx.com"); + + AliPayApi.batchTrans(params, aliPayBean.getPrivateKey(), signType, response); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + /** + * 地铁购票核销码发码 + */ + @RequestMapping(value = "/voucherGenerate") + @ResponseBody + public String voucherGenerate(@RequestParam("tradeNo") String tradeNo) { + try { + //需要支付成功的订单号 +// String tradeNo = getPara("tradeNo"); + + AlipayCommerceCityfacilitatorVoucherGenerateModel model = new AlipayCommerceCityfacilitatorVoucherGenerateModel(); + model.setCityCode("440300"); + model.setTradeNo(tradeNo); + model.setTotalFee("8"); + model.setTicketNum("2"); + model.setTicketType("oneway"); + model.setSiteBegin("001"); + model.setSiteEnd("002"); + model.setTicketPrice("4"); + return AliPayApi.voucherGenerateToResponse(model).getBody(); + } catch (AlipayApiException e) { + e.printStackTrace(); + } + return null; + } + + @RequestMapping(value = "/return_url") + @ResponseBody + public String returnUrl(HttpServletRequest request) { + try { + // 获取支付宝GET过来反馈信息 + Map map = AliPayApi.toMap(request); + for (Map.Entry entry : map.entrySet()) { + System.out.println(entry.getKey() + " = " + entry.getValue()); + } + + boolean verifyResult = AlipaySignature.rsaCheckV1(map, aliPayBean.getPublicKey(), "UTF-8", + "RSA2"); + + if (verifyResult) { + // TODO 请在这里加上商户的业务逻辑程序代码 + System.out.println("return_url 验证成功"); + + return "success"; + } else { + System.out.println("return_url 验证失败"); + // TODO + return "failure"; + } + } catch (AlipayApiException e) { + e.printStackTrace(); + return "failure"; + } + } + + @RequestMapping(value = "/cert_return_url") + @ResponseBody + public String certReturnUrl(HttpServletRequest request) { + try { + // 获取支付宝GET过来反馈信息 + Map map = AliPayApi.toMap(request); + for (Map.Entry entry : map.entrySet()) { + System.out.println(entry.getKey() + " = " + entry.getValue()); + } + + boolean verifyResult = AlipaySignature.rsaCertCheckV1(map, aliPayBean.getAliPayCertPath(), "UTF-8", + "RSA2"); + + if (verifyResult) { + // TODO 请在这里加上商户的业务逻辑程序代码 + System.out.println("certReturnUrl 验证成功"); + + return "success"; + } else { + System.out.println("certReturnUrl 验证失败"); + // TODO + return "failure"; + } + } catch (AlipayApiException e) { + e.printStackTrace(); + return "failure"; + } + } + + + @RequestMapping(value = "/callback") + @ResponseBody + public String notifyUrl(HttpServletRequest request) { + try { + // 获取支付宝POST过来反馈信息 + Map params = AliPayApi.toMap(request); + + for (Map.Entry entry : params.entrySet()) { + System.out.println(entry.getKey() + " = " + entry.getValue()); + } + + boolean verifyResult = AlipaySignature.rsaCheckV1(params, aliPayBean.getPublicKey(), "UTF-8", "RSA2"); + + if (verifyResult) { + // TODO 请在这里加上商户的业务逻辑程序代码 异步通知可能出现订单重复通知 需要做去重处理 + System.out.println("notify_url 验证成功succcess"); + String outTradeNo = params.get("out_trade_no"); + remoteUUserService.paySuccess(Long.valueOf(outTradeNo), "inner"); + return "success"; + } else { + System.out.println("notify_url 验证失败"); + // TODO + return "failure"; + } + } catch (AlipayApiException e) { + e.printStackTrace(); + return "failure"; + } + } + + @RequestMapping(value = "/cert_notify_url") + @ResponseBody + public String certNotifyUrl(HttpServletRequest request) { + try { + // 获取支付宝POST过来反馈信息 + Map params = AliPayApi.toMap(request); + + for (Map.Entry entry : params.entrySet()) { + System.out.println(entry.getKey() + " = " + entry.getValue()); + } + + boolean verifyResult = AlipaySignature.rsaCertCheckV1(params, aliPayBean.getAliPayCertPath(), "UTF-8", "RSA2"); + + if (verifyResult) { + // TODO 请在这里加上商户的业务逻辑程序代码 异步通知可能出现订单重复通知 需要做去重处理 + System.out.println("certNotifyUrl 验证成功succcess"); + return "success"; + } else { + System.out.println("certNotifyUrl 验证失败"); + // TODO + return "failure"; + } + } catch (AlipayApiException e) { + e.printStackTrace(); + return "failure"; + } + } + +} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/config/CcpayConfig.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/config/CcpayConfig.java similarity index 93% rename from wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/config/CcpayConfig.java rename to wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/config/CcpayConfig.java index f407466..6f0be0b 100644 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/config/CcpayConfig.java +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/config/CcpayConfig.java @@ -1,4 +1,4 @@ -package org.wfc.payment.ccpay.config; +package org.wfc.payment.pay.ccpay.config; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/controller/CcpayController.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/controller/CcpayController.java similarity index 83% rename from wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/controller/CcpayController.java rename to wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/controller/CcpayController.java index 81efdd0..eeed880 100644 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/controller/CcpayController.java +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/controller/CcpayController.java @@ -1,15 +1,15 @@ -package org.wfc.payment.ccpay.controller; +package org.wfc.payment.pay.ccpay.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; -import org.wfc.payment.ccpay.model.PaymentRequest; -import org.wfc.payment.ccpay.model.PaymentResponse; -import org.wfc.payment.ccpay.model.UCreditCardToken; -import org.wfc.payment.ccpay.model.RefundResponse; -import org.wfc.payment.ccpay.model.RefundRequest; -import org.wfc.payment.ccpay.service.IUCreditCardOrderService; -import org.wfc.payment.ccpay.service.IUCreditCardTokenService; +import org.wfc.payment.pay.ccpay.model.PaymentRequest; +import org.wfc.payment.pay.ccpay.model.PaymentResponse; +import org.wfc.payment.pay.ccpay.model.UCreditCardToken; +import org.wfc.payment.pay.ccpay.model.RefundResponse; +import org.wfc.payment.pay.ccpay.model.RefundRequest; +import org.wfc.payment.pay.ccpay.service.IUCreditCardOrderService; +import org.wfc.payment.pay.ccpay.service.IUCreditCardTokenService; /** * Credit card payment controller diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/exception/RuntimeException.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/exception/RuntimeException.java similarity index 82% rename from wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/exception/RuntimeException.java rename to wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/exception/RuntimeException.java index 9fe42a4..e7cede8 100644 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/exception/RuntimeException.java +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/exception/RuntimeException.java @@ -1,4 +1,4 @@ -package org.wfc.payment.ccpay.exception; +package org.wfc.payment.pay.ccpay.exception; public class RuntimeException extends Exception { diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/mapper/UCreditCardOrderMapper.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/mapper/UCreditCardOrderMapper.java similarity index 73% rename from wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/mapper/UCreditCardOrderMapper.java rename to wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/mapper/UCreditCardOrderMapper.java index 1fed5f1..0215742 100644 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/mapper/UCreditCardOrderMapper.java +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/mapper/UCreditCardOrderMapper.java @@ -1,8 +1,8 @@ -package org.wfc.payment.ccpay.mapper; +package org.wfc.payment.pay.ccpay.mapper; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; -import org.wfc.payment.ccpay.model.UCreditCardOrder; +import org.wfc.payment.pay.ccpay.model.UCreditCardOrder; @Mapper public interface UCreditCardOrderMapper { diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/mapper/UCreditCardTokenMapper.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/mapper/UCreditCardTokenMapper.java similarity index 72% rename from wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/mapper/UCreditCardTokenMapper.java rename to wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/mapper/UCreditCardTokenMapper.java index 4390438..ccc89df 100644 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/mapper/UCreditCardTokenMapper.java +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/mapper/UCreditCardTokenMapper.java @@ -1,8 +1,8 @@ -package org.wfc.payment.ccpay.mapper; +package org.wfc.payment.pay.ccpay.mapper; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; -import org.wfc.payment.ccpay.model.UCreditCardToken; +import org.wfc.payment.pay.ccpay.model.UCreditCardToken; @Mapper public interface UCreditCardTokenMapper { diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/model/PaymentRequest.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/model/PaymentRequest.java similarity index 95% rename from wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/model/PaymentRequest.java rename to wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/model/PaymentRequest.java index 49a43a3..286be69 100644 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/model/PaymentRequest.java +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/model/PaymentRequest.java @@ -1,4 +1,4 @@ -package org.wfc.payment.ccpay.model; +package org.wfc.payment.pay.ccpay.model; import lombok.Data; diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/model/PaymentResponse.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/model/PaymentResponse.java similarity index 78% rename from wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/model/PaymentResponse.java rename to wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/model/PaymentResponse.java index 55eb8cd..ba2bcb2 100644 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/model/PaymentResponse.java +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/model/PaymentResponse.java @@ -1,4 +1,4 @@ -package org.wfc.payment.ccpay.model; +package org.wfc.payment.pay.ccpay.model; import lombok.Data; diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/model/RefundRequest.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/model/RefundRequest.java similarity index 94% rename from wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/model/RefundRequest.java rename to wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/model/RefundRequest.java index bd22139..42cc891 100644 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/model/RefundRequest.java +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/model/RefundRequest.java @@ -1,4 +1,4 @@ -package org.wfc.payment.ccpay.model; +package org.wfc.payment.pay.ccpay.model; public class RefundRequest { private String transactionId; diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/model/RefundResponse.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/model/RefundResponse.java similarity index 91% rename from wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/model/RefundResponse.java rename to wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/model/RefundResponse.java index 1431585..c843d5a 100644 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/model/RefundResponse.java +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/model/RefundResponse.java @@ -1,4 +1,4 @@ -package org.wfc.payment.ccpay.model; +package org.wfc.payment.pay.ccpay.model; public class RefundResponse { private String status; diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/model/UCreditCardOrder.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/model/UCreditCardOrder.java similarity index 96% rename from wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/model/UCreditCardOrder.java rename to wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/model/UCreditCardOrder.java index e379bc4..79d2c4b 100644 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/model/UCreditCardOrder.java +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/model/UCreditCardOrder.java @@ -1,4 +1,4 @@ -package org.wfc.payment.ccpay.model; +package org.wfc.payment.pay.ccpay.model; import javax.persistence.*; import java.math.BigDecimal; diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/model/UCreditCardToken.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/model/UCreditCardToken.java similarity index 96% rename from wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/model/UCreditCardToken.java rename to wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/model/UCreditCardToken.java index fd4c402..f9ff901 100644 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/model/UCreditCardToken.java +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/model/UCreditCardToken.java @@ -1,4 +1,4 @@ -package org.wfc.payment.ccpay.model; +package org.wfc.payment.pay.ccpay.model; import javax.persistence.*; import java.time.LocalDateTime; diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/service/IUCreditCardOrderService.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/service/IUCreditCardOrderService.java similarity index 54% rename from wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/service/IUCreditCardOrderService.java rename to wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/service/IUCreditCardOrderService.java index 573297c..b4650c4 100644 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/service/IUCreditCardOrderService.java +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/service/IUCreditCardOrderService.java @@ -1,10 +1,10 @@ -package org.wfc.payment.ccpay.service; +package org.wfc.payment.pay.ccpay.service; -import org.wfc.payment.ccpay.model.PaymentRequest; -import org.wfc.payment.ccpay.model.PaymentResponse; -import org.wfc.payment.ccpay.model.RefundRequest; -import org.wfc.payment.ccpay.model.RefundResponse; -import org.wfc.payment.ccpay.model.UCreditCardOrder; +import org.wfc.payment.pay.ccpay.model.PaymentRequest; +import org.wfc.payment.pay.ccpay.model.PaymentResponse; +import org.wfc.payment.pay.ccpay.model.RefundRequest; +import org.wfc.payment.pay.ccpay.model.RefundResponse; +import org.wfc.payment.pay.ccpay.model.UCreditCardOrder; public interface IUCreditCardOrderService { diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/service/IUCreditCardTokenService.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/service/IUCreditCardTokenService.java new file mode 100644 index 0000000..a6d7e53 --- /dev/null +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/service/IUCreditCardTokenService.java @@ -0,0 +1,13 @@ +package org.wfc.payment.pay.ccpay.service; + +import org.wfc.payment.pay.ccpay.model.PaymentRequest; +import org.wfc.payment.pay.ccpay.model.UCreditCardToken; + +public interface IUCreditCardTokenService { + + void saveToken(UCreditCardToken token); + + UCreditCardToken getTokenByUserId(Long userId); + + String getPaymentToken(PaymentRequest paymentRequest); +} \ No newline at end of file diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/service/impl/UCreditCardOrderServiceImpl.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/service/impl/UCreditCardOrderServiceImpl.java similarity index 91% rename from wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/service/impl/UCreditCardOrderServiceImpl.java rename to wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/service/impl/UCreditCardOrderServiceImpl.java index 194b07d..67fac7a 100644 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/service/impl/UCreditCardOrderServiceImpl.java +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/service/impl/UCreditCardOrderServiceImpl.java @@ -1,4 +1,4 @@ -package org.wfc.payment.ccpay.service.impl; +package org.wfc.payment.pay.ccpay.service.impl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpEntity; @@ -8,14 +8,14 @@ import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import org.springframework.core.ParameterizedTypeReference; -import org.wfc.payment.ccpay.config.CcpayConfig; -import org.wfc.payment.ccpay.mapper.UCreditCardOrderMapper; -import org.wfc.payment.ccpay.model.PaymentRequest; -import org.wfc.payment.ccpay.model.PaymentResponse; -import org.wfc.payment.ccpay.model.RefundRequest; -import org.wfc.payment.ccpay.model.RefundResponse; -import org.wfc.payment.ccpay.model.UCreditCardOrder; -import org.wfc.payment.ccpay.service.IUCreditCardOrderService; +import org.wfc.payment.pay.ccpay.config.CcpayConfig; +import org.wfc.payment.pay.ccpay.mapper.UCreditCardOrderMapper; +import org.wfc.payment.pay.ccpay.model.PaymentRequest; +import org.wfc.payment.pay.ccpay.model.PaymentResponse; +import org.wfc.payment.pay.ccpay.model.RefundRequest; +import org.wfc.payment.pay.ccpay.model.RefundResponse; +import org.wfc.payment.pay.ccpay.model.UCreditCardOrder; +import org.wfc.payment.pay.ccpay.service.IUCreditCardOrderService; import java.util.HashMap; diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/service/impl/UCreditCardTokenServiceImpl.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/service/impl/UCreditCardTokenServiceImpl.java similarity index 72% rename from wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/service/impl/UCreditCardTokenServiceImpl.java rename to wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/service/impl/UCreditCardTokenServiceImpl.java index 62af752..be622d4 100644 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/ccpay/service/impl/UCreditCardTokenServiceImpl.java +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/ccpay/service/impl/UCreditCardTokenServiceImpl.java @@ -1,11 +1,11 @@ -package org.wfc.payment.ccpay.service.impl; +package org.wfc.payment.pay.ccpay.service.impl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.wfc.payment.ccpay.mapper.UCreditCardTokenMapper; -import org.wfc.payment.ccpay.model.PaymentRequest; -import org.wfc.payment.ccpay.model.UCreditCardToken; -import org.wfc.payment.ccpay.service.IUCreditCardTokenService; +import org.wfc.payment.pay.ccpay.mapper.UCreditCardTokenMapper; +import org.wfc.payment.pay.ccpay.model.PaymentRequest; +import org.wfc.payment.pay.ccpay.model.UCreditCardToken; +import org.wfc.payment.pay.ccpay.service.IUCreditCardTokenService; @Service public class UCreditCardTokenServiceImpl implements IUCreditCardTokenService { diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/jdpay/controller/AppParams.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/jdpay/controller/AppParams.java new file mode 100644 index 0000000..35c2239 --- /dev/null +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/jdpay/controller/AppParams.java @@ -0,0 +1,66 @@ +/** + * + *

京东APP支付

+ * + * @author cyc + */ +package org.wfc.payment.pay.jdpay.controller; + +public class AppParams { + private String orderId; + private String merchant; + private String appId; + private String signData; + private String extraInfo; + + public AppParams() { + } + + public AppParams(String orderId, String merchant, String appId, String signData, String extraInfo) { + this.orderId = orderId; + this.merchant = merchant; + this.appId = appId; + this.signData = signData; + this.extraInfo = extraInfo; + } + + public String getOrderId() { + return orderId; + } + + public void setOrderId(String orderId) { + this.orderId = orderId; + } + + public String getMerchant() { + return merchant; + } + + public void setMerchant(String merchant) { + this.merchant = merchant; + } + + public String getAppId() { + return appId; + } + + public void setAppId(String appId) { + this.appId = appId; + } + + public String getSignData() { + return signData; + } + + public void setSignData(String signData) { + this.signData = signData; + } + + public String getExtraInfo() { + return extraInfo; + } + + public void setExtraInfo(String extraInfo) { + this.extraInfo = extraInfo; + } +} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/jdpay/controller/JdPayController.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/jdpay/controller/JdPayController.java new file mode 100644 index 0000000..fe610f9 --- /dev/null +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/jdpay/controller/JdPayController.java @@ -0,0 +1,359 @@ +package org.wfc.payment.pay.jdpay.controller; + +import cn.hutool.core.codec.Base64; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.XmlUtil; +import com.ijpay.jdpay.JdPayApi; +import com.ijpay.jdpay.kit.JdPayKit; +import com.ijpay.jdpay.model.CustomerPayModel; +import com.ijpay.jdpay.model.FkmModel; +import com.ijpay.jdpay.model.QueryBaiTiaoFqModel; +import com.ijpay.jdpay.model.QueryOrderModel; +import com.ijpay.jdpay.model.RefundModel; +import com.ijpay.jdpay.model.SaveOrderModel; +import com.ijpay.jdpay.model.UniOrderModel; +import com.ijpay.jdpay.model.UserRelationModel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.servlet.ModelAndView; +import org.wfc.payment.domain.JdPayBean; +import org.wfc.payment.domain.vo.AjaxResult; + +import java.util.Date; +import java.util.Map; + +/** + * + *

微信支付 Demo

+ * + * @author cyc + */ +@Controller +@RequestMapping("/JDPay") +public class JdPayController { + private Logger log = LoggerFactory.getLogger(this.getClass()); + + @Autowired + JdPayBean jdPayBean; + + @GetMapping("/test") + @ResponseBody + public JdPayBean test() { + return jdPayBean; + } + + /** + * App 支付 + * + * @return + */ + @RequestMapping(value = "/appPay", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public AjaxResult appPay() { + String reqXml = UniOrderModel.builder() + .version("V2.0") + .merchant(jdPayBean.getMchId()) + .tradeNum(System.currentTimeMillis() + "") + .tradeName("IJPay 让支付触手可及") + .tradeDesc("https://gitee.com/javen205/IJPay") + .tradeTime(DateUtil.format(new Date(), "yyyyMMddHHmmss")) + .amount("1") + .orderType("1") + .currency("CNY") + .note("备注") + .notifyUrl("http://jdpaydemo.jd.com/asynNotify.htm") + .tradeType("GEN") + .build() + .genReqXml(jdPayBean.getRsaPrivateKey(), jdPayBean.getDesKey(), "V2.0", jdPayBean.getMchId()); + + // 执行请求 + String resultData = JdPayApi.uniOrder(reqXml); + + log.info("resultData:" + resultData); + + // 解析响应的 xml 数据 + Map map = JdPayKit.parseResp(resultData); + + String code = map.get("code"); + String encrypt = map.get("encrypt"); + if (!"000000".equals(code)) { + String desc = map.get("desc"); + return new AjaxResult().addError(desc); + } + // 解密并验证签名 + String decrypt = JdPayKit.decrypt(jdPayBean.getRsaPublicKey(), jdPayBean.getDesKey(), encrypt); + + log.info("decrypt>" + decrypt); + + // 将 xml 转化为 map + Map toMap = XmlUtil.xmlToMap(decrypt); + + log.info("result toMap>" + toMap); + + + String orderId = (String) toMap.get("orderId"); + + StringBuilder sb = new StringBuilder(); + sb.append("merchant=").append(jdPayBean.getMchId()); + sb.append("&orderId=").append(orderId); + sb.append("&key=").append("test"); + String sign = JdPayKit.md5LowerCase(sb.toString()); + + return new AjaxResult().success(new AppParams(orderId, jdPayBean.getMchId(), "123456789", + sign, "123456789")); + } + + /** + * PC H5 支付 + * + * @param payType + * @return + */ + @RequestMapping(value = "/saveOrder", method = {RequestMethod.POST, RequestMethod.GET}) + public ModelAndView saveOrder(@RequestParam("payType") String payType) { + + ModelAndView mv = new ModelAndView(); + + Map map = SaveOrderModel.builder() + .version("V2.0") + .merchant(jdPayBean.getMchId()) + .tradeNum(System.currentTimeMillis() + "") + .tradeName("IJPay") + .tradeDesc("IJPay 让支付触手可及") + .tradeTime(DateUtil.format(new Date(), "yyyyMMddHHmmss")) + .amount("10000") + .orderType("0") + .currency("CNY") + .note("IJPay 了解一下") + .callbackUrl("https://jdpay.com") + .notifyUrl("https://jdpay.com") + .userId("IJPay001") + .build() + .createSign(jdPayBean.getRsaPrivateKey(), jdPayBean.getDesKey()); + + mv.addObject("map", map); + mv.addObject("payUrl", payType.equals("pc") ? JdPayApi.PC_SAVE_ORDER_URL : JdPayApi.H5_SAVE_ORDER_URL); + mv.setViewName("jd_pc_h5.html"); + return mv; + } + + /** + * 商户二维码支付 + */ + @RequestMapping(value = "/customerPay", method = {RequestMethod.POST, RequestMethod.GET}) + public ModelAndView customerPay() { + + ModelAndView mv = new ModelAndView(); + + Map map = CustomerPayModel.builder() + .version("V2.0") + .merchant(jdPayBean.getMchId()) + .tradeNum(System.currentTimeMillis() + "") + .tradeName("IJPay") + .tradeDesc("IJPay 让支付触手可及") + .tradeTime(DateUtil.format(new Date(), "yyyyMMddHHmmss")) +// .amount("1000") + .orderType("0") + .currency("CNY") + .note("IJPay 了解一下") + .notifyUrl("https://jdpay.com") + .build() + .createSign(jdPayBean.getRsaPrivateKey(), jdPayBean.getDesKey()); + + mv.addObject("map", map); + mv.addObject("payUrl", JdPayApi.CUSTOMER_PAY_URL); + mv.setViewName("jd_customer_pay.html"); + return mv; + } + + @RequestMapping(value = "/queryOrder", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public AjaxResult queryOrder(@RequestParam("tradeType") String tradeType, + @RequestParam("oTradeNum") String oTradeNum, + @RequestParam("tradeNum") String tradeNum) { + String reqXml = QueryOrderModel.builder() + .version("V2.0") + .merchant(jdPayBean.getMchId()) + .tradeNum(tradeNum) + .tradeType(tradeType) + .oTradeNum(oTradeNum) + .build() + .genReqXml(jdPayBean.getRsaPrivateKey(), jdPayBean.getDesKey(), "V2.0", jdPayBean.getMchId()); + String queryResult = JdPayApi.queryOrder(reqXml); + log.info("queryResult:" + queryResult); + + // 解析响应的 xml 数据 + Map map = JdPayKit.parseResp(queryResult); + + String code = map.get("code"); + String encrypt = map.get("encrypt"); + if (!"000000".equals(code)) { + String desc = map.get("desc"); + return new AjaxResult().addError(desc); + } + // 解密并验证签名 + String decrypt = JdPayKit.decrypt(jdPayBean.getRsaPublicKey(), jdPayBean.getDesKey(), encrypt); + + log.info("decrypt>" + decrypt); + + return new AjaxResult().success(decrypt); + } + + @RequestMapping(value = "/fkmPay", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public AjaxResult fkmPay(@RequestParam("token") String token, + @RequestParam("amount") String amount) { + String reqXml = FkmModel.builder() + .token(token) + .version("V2.0") + .merchant(jdPayBean.getMchId()) + .device("IJPay Dev") + .tradeNum(System.currentTimeMillis() + "") + .tradeName("IJPay 刷卡支付") + .tradeDesc("IJPay 了解一下") + .tradeTime(DateUtil.format(new Date(), "yyyyMMddHHmmss")) + .amount(amount) + .currency("CNY") + .note("备注") + .notifyUrl("https://gitee.com/javen205/IJPay") + .build() + .genReqXml(jdPayBean.getRsaPrivateKey(), jdPayBean.getDesKey(), "V2.0", jdPayBean.getMchId()); + String queryResult = JdPayApi.fkmPay(reqXml); + log.info("queryResult:" + queryResult); + + // 解析响应的 xml 数据 + Map map = JdPayKit.parseResp(queryResult); + + String code = map.get("code"); + String encrypt = map.get("encrypt"); + if (!"000000".equals(code)) { + String desc = map.get("desc"); + return new AjaxResult().addError(desc); + } + // 解密并验证签名 + String decrypt = JdPayKit.decrypt(jdPayBean.getRsaPublicKey(), jdPayBean.getDesKey(), encrypt); + + log.info("decrypt>" + decrypt); + + return new AjaxResult().success(decrypt); + } + + @RequestMapping(value = "/userRelation", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public AjaxResult userRelation(@RequestParam("userId") String userId, + @RequestParam("type") String type) { + String reqXml = UserRelationModel.builder() + .version("V2.0") + .merchant(jdPayBean.getMchId()) + .userId(userId) + .build() + .genReqXml(jdPayBean.getRsaPrivateKey(), jdPayBean.getDesKey(), "V2.0", jdPayBean.getMchId()); + + String result = null; + + if ("get".equals(type)) { + result = JdPayApi.getUserRelation(reqXml); + } else { + result = JdPayApi.cancelUserRelation(reqXml); + } + + log.info(result); + + // 解析响应的 xml 数据 + Map map = JdPayKit.parseResp(result); + + String code = map.get("code"); + String encrypt = map.get("encrypt"); + if (!"000000".equals(code)) { + String desc = map.get("desc"); + return new AjaxResult().addError(desc); + } + // 解密并验证签名 + String decrypt = JdPayKit.decrypt(jdPayBean.getRsaPublicKey(), jdPayBean.getDesKey(), encrypt); + + log.info("decrypt>" + decrypt); + + Map toMap = XmlUtil.xmlToMap(decrypt); + System.out.println(toMap); + return new AjaxResult().success(decrypt); + } + + @RequestMapping(value = "/refund", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public AjaxResult refund(@RequestParam("amount") String amount, + @RequestParam("oTradeNum") String oTradeNum, + @RequestParam("tradeNum") String tradeNum) { + + System.out.println(Base64.encode(FileUtil.readBytes(jdPayBean.getCertPath()))); + String reqXml = RefundModel.builder() + .version("V2.0") + .merchant(jdPayBean.getMchId()) + .tradeNum(tradeNum) + .oTradeNum(oTradeNum) + .amount(amount) + .currency("CNY") + .build() + .genReqXml(jdPayBean.getRsaPrivateKey(), jdPayBean.getDesKey(), "V2.0", jdPayBean.getMchId()); + String queryResult = JdPayApi.refund(reqXml); + log.info("queryResult:" + queryResult); + + // 解析响应的 xml 数据 + Map map = JdPayKit.parseResp(queryResult); + + String code = map.get("code"); + String encrypt = map.get("encrypt"); + if (!"000000".equals(code)) { + String desc = map.get("desc"); + return new AjaxResult().addError(desc); + } + // 解密并验证签名 + String decrypt = JdPayKit.decrypt(jdPayBean.getRsaPublicKey(), jdPayBean.getDesKey(), encrypt); + + log.info("decrypt>" + decrypt); + + return new AjaxResult().success(decrypt); + } + + + @RequestMapping(value = "/queryBaiTiaoFq", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public AjaxResult queryBaiTiaoFq(@RequestParam("amount") String amount) { + String reqXml = QueryBaiTiaoFqModel.builder() + .version("V2.0") + .merchant(jdPayBean.getMchId()) + .tradeNum(System.currentTimeMillis() + "") + .amount(amount) + .build() + .genReqXml(jdPayBean.getRsaPrivateKey(), jdPayBean.getDesKey(), "V2.0", jdPayBean.getMchId()); + + String baiTiaoResult = JdPayApi.queryBaiTiaoFq(reqXml); + + log.info(baiTiaoResult); + + // 解析响应的 xml 数据 + Map map = JdPayKit.parseResp(baiTiaoResult); + + String code = map.get("code"); + String encrypt = map.get("encrypt"); + if (!"000000".equals(code)) { + String desc = map.get("desc"); + return new AjaxResult().addError(desc); + } + // 解密并验证签名 + String decrypt = JdPayKit.decrypt(jdPayBean.getRsaPublicKey(), jdPayBean.getDesKey(), encrypt); + + log.info("decrypt>" + decrypt); + + Map toMap = XmlUtil.xmlToMap(decrypt); + System.out.println(toMap); + return new AjaxResult().success(decrypt); + } +} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/paypal/controller/PayPalController.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/paypal/controller/PayPalController.java new file mode 100644 index 0000000..a5db896 --- /dev/null +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/paypal/controller/PayPalController.java @@ -0,0 +1,297 @@ +/** + * + *

PayPal 支付示例

+ * + * @author cyc + */ +package org.wfc.payment.pay.paypal.controller; + +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.ijpay.core.IJPayHttpResponse; +import com.ijpay.core.kit.HttpKit; +import com.ijpay.core.kit.PayKit; +import com.ijpay.paypal.PayPalApi; +import com.ijpay.paypal.PayPalApiConfig; +import com.ijpay.paypal.PayPalApiConfigKit; +import com.ijpay.paypal.accesstoken.AccessToken; +import com.ijpay.paypal.accesstoken.AccessTokenKit; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.wfc.payment.domain.PayPalBean; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +@Controller +@RequestMapping("/payPal") +public class PayPalController { + private Logger log = LoggerFactory.getLogger(this.getClass()); + + @Autowired + PayPalBean payPalBean; + + private final static String RETURN_URL = "/payPal/return"; + private final static String CANCEL_URL = "/payPal/cancel"; + + @RequestMapping("test") + @ResponseBody + public PayPalBean test() { + return payPalBean; + } + + public PayPalApiConfig getConfig() { + PayPalApiConfig config = new PayPalApiConfig(); + config.setClientId(payPalBean.getClientId()); + config.setSecret(payPalBean.getSecret()); + config.setSandBox(payPalBean.getSandBox()); + config.setDomain(payPalBean.getDomain()); + PayPalApiConfigKit.setThreadLocalApiConfig(config); + return config; + } + + @RequestMapping(value = "/getAccessToken") + @ResponseBody + public AccessToken getAccessToken() { + try { + getConfig(); + return AccessTokenKit.get(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + @RequestMapping(value = "/createOrder") + @ResponseBody + public void createOrder(HttpServletResponse response) { + try { + PayPalApiConfig config = getConfig(); + + //参数请求参数文档 https://developer.paypal.com/docs/api/orders/v2/#orders_create + Map dataMap = new HashMap<>(); + dataMap.put("intent", "CAPTURE"); + + ArrayList> list = new ArrayList<>(); + + Map amount = new HashMap<>(); + amount.put("currency_code", "USD"); + amount.put("value", "0.01"); + + Map itemMap = new HashMap<>(); + itemMap.put("amount", amount); + + list.add(itemMap); + + dataMap.put("purchase_units", list); + + Map card = new HashMap<>(); + card.put("name", "test buyer"); + card.put("number", "4231220385792723"); + card.put("security_code", "123"); + card.put("expiry", "2029-07"); + + Map experienceContext = new HashMap<>(); + experienceContext.put("cancel_url", config.getDomain().concat(CANCEL_URL)); + experienceContext.put("return_url", config.getDomain().concat(RETURN_URL)); + Map> paymentSource = new HashMap<>(); + paymentSource.put("experience_context",experienceContext); + paymentSource.put("card",card); + +// dataMap.put("payment_source", paymentSource); + + String data = JSONUtil.toJsonStr(dataMap); + log.info(data); + IJPayHttpResponse resData = PayPalApi.createOrder(config, data); + log.info(resData.toString()); + if (resData.getStatus() == 201) { + String resultStr = resData.getBody(); + + JSONObject jsonObject = JSONUtil.parseObj(resultStr); + JSONArray links = jsonObject.getJSONArray("links"); + for (int i = 0; i < links.size(); i++) { + JSONObject item = links.getJSONObject(i); + String rel = item.getStr("rel"); + String href = item.getStr("href"); + if ("approve".equalsIgnoreCase(rel)) { + response.sendRedirect(href); + break; + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + @RequestMapping(value = "/updateOrder") + @ResponseBody + public String updateOrder(@RequestParam("id") String id) { + try { + PayPalApiConfig config = getConfig(); + // https://developer.paypal.com/docs/api/orders/v2/#orders_patch + + ArrayList> updateData = new ArrayList<>(); + + Map itemMap = new HashMap<>(); + itemMap.put("op", "replace"); + itemMap.put("path", "/purchase_units/@reference_id=='default'/amount"); + + Map amount = new HashMap<>(); + amount.put("currency_code", "USD"); + amount.put("value", "199.00"); + + itemMap.put("value", amount); + + updateData.add(itemMap); + + String data = JSONUtil.toJsonStr(updateData); + log.info(data); + IJPayHttpResponse resData = PayPalApi.updateOrder(config, id, data); + log.info(resData.toString()); + if (resData.getStatus() == 204) { + return "success"; + } + return "接口请求错误码为:" + resData.getStatus(); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + @RequestMapping(value = "/queryOrder") + @ResponseBody + public String queryOrder(@RequestParam("id") String id) { + try { + PayPalApiConfig config = getConfig(); + IJPayHttpResponse response = PayPalApi.queryOrder(config, id); + log.info(response.toString()); + if (response.getStatus() == 200) { + return response.getBody(); + } else { + return "接口请求错误码为:" + response.getStatus(); + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + @RequestMapping(value = "/captureOrder") + @ResponseBody + public String captureOrder(@RequestParam("id") String id) { + try { + PayPalApiConfig config = getConfig(); + IJPayHttpResponse response = PayPalApi.captureOrder(config, id, ""); + log.info(response.toString()); + if (response.getStatus() == 200 || response.getStatus() == 201) { + return response.getBody(); + } else { + return "接口请求错误码为:" + response.getStatus(); + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + @RequestMapping(value = "/captureQuery") + @ResponseBody + public String captureQuery(@RequestParam("captureId") String captureId) { + try { + PayPalApiConfig config = getConfig(); + IJPayHttpResponse response = PayPalApi.captureQuery(config, captureId); + log.info(response.toString()); + if (response.getStatus() == 200) { + return response.getBody(); + } else { + return "接口请求错误码为:" + response.getStatus(); + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + @RequestMapping(value = "/refund") + @ResponseBody + public String refund(@RequestParam("id") String id) { + try { + PayPalApiConfig config = getConfig(); + System.out.println("id>" + id); + + Map map = new HashMap<>(); + map.put("invoice_id", PayKit.generateStr()); + map.put("note_to_payer", "test product"); + + Map amount = new HashMap<>(); + amount.put("value", "1.00"); + amount.put("currency_code", "USD"); + + map.put("amount", amount); + + String data = JSONUtil.toJsonStr(map); + log.info("refund data:" + data); + IJPayHttpResponse response = PayPalApi.refund(config, id, data); + log.info(response.toString()); + if (response.getStatus() == 201) { + return response.getBody(); + } else { + return "接口请求错误码为:" + response.getStatus(); + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + @RequestMapping(value = "/refundQuery") + @ResponseBody + public String refundQuery(@RequestParam("id") String id) { + try { + PayPalApiConfig config = getConfig(); + IJPayHttpResponse response = PayPalApi.refundQuery(config, id); + log.info(response.toString()); + if (response.getStatus() == 200) { + return response.getBody(); + } else { + return "接口请求错误码为:" + response.getStatus(); + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + @RequestMapping(value = "/return") + @ResponseBody + public String returnUrl(HttpServletRequest request) { + try { + String token = request.getParameter("token"); + String payerId = request.getParameter("PayerID"); + log.info("token:" + token); + log.info("payerId:" + payerId); + return token; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + @RequestMapping(value = "/cancel") + @ResponseBody + public String cancelUrl(HttpServletRequest request, HttpServletResponse response) { + String readData = HttpKit.readData(request); + System.out.println(readData); + return readData; + } +} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/unionpay/controller/UnionPayController.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/unionpay/controller/UnionPayController.java new file mode 100644 index 0000000..58f8149 --- /dev/null +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/unionpay/controller/UnionPayController.java @@ -0,0 +1,551 @@ +package org.wfc.payment.pay.unionpay.controller; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.ijpay.core.enums.SignType; +import com.ijpay.core.kit.HttpKit; +import com.ijpay.core.kit.IpKit; +import com.ijpay.core.kit.WxPayKit; +import com.ijpay.unionpay.UnionPayApi; +import com.ijpay.unionpay.enums.ServiceEnum; +import com.ijpay.unionpay.model.AuthCodeToOpenIdModel; +import com.ijpay.unionpay.model.BillDownloadModel; +import com.ijpay.unionpay.model.MicroPayModel; +import com.ijpay.unionpay.model.OrderQueryModel; +import com.ijpay.unionpay.model.RefundModel; +import com.ijpay.unionpay.model.RefundQueryModel; +import com.ijpay.unionpay.model.UnifiedOrderModel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.wfc.payment.domain.UnionPayBean; +import org.wfc.payment.domain.vo.AjaxResult; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +@Controller +@RequestMapping("/unionPay") +public class UnionPayController { + private static final Logger logger = LoggerFactory.getLogger(UnionPayController.class); + + @Autowired + UnionPayBean unionPayBean; + + @RequestMapping("test") + @ResponseBody + public UnionPayBean test() { + return unionPayBean; + } + + /** + * 刷卡支付 + */ + @RequestMapping(value = "/microPay", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public AjaxResult microPay(HttpServletRequest request, HttpServletResponse response) { + try { + String authCode = request.getParameter("authCode"); + String totalFee = request.getParameter("totalFee"); + + String ip = IpKit.getRealIp(request); + if (StrUtil.isBlank(ip)) { + ip = "127.0.0.1"; + } + + Map params = MicroPayModel.builder() + .service(ServiceEnum.MICRO_PAY.toString()) + .mch_id(unionPayBean.getMachId()) + .out_trade_no(WxPayKit.generateStr()) + .body("IJPay 云闪付测试") + .attach("聚合支付 SDK") + .total_fee(totalFee) + .mch_create_ip(ip) + .auth_code(authCode) + .nonce_str(WxPayKit.generateStr()) + .build() + .createSign(unionPayBean.getKey(), SignType.MD5); + + logger.info("请求参数:" + JSONUtil.toJsonStr(params)); + + String xmlResult = UnionPayApi.execution(unionPayBean.getServerUrl(), params); + logger.info("xmlResult:" + xmlResult); + Map result = WxPayKit.xmlToMap(xmlResult); + String returnCode = result.get("status"); + String resultCode = result.get("result_code"); + String errMsg = result.get("err_msg"); + String errCode = result.get("err_code"); + + if (!"0".equals(returnCode) || !"0".equals(resultCode)) { + return new AjaxResult().addError("errCode:" + errCode + " errMsg:" + errMsg); + } + return new AjaxResult().success(result); + } catch (Exception e) { + e.printStackTrace(); + return new AjaxResult().addError(e.getMessage()); + } + } + + @RequestMapping(value = "/queryOrder", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public AjaxResult query(@RequestParam(value = "transactionId", required = false) String transactionId, + @RequestParam(value = "outTradeNo", required = false) String outTradeNo) { + try { + + if (StrUtil.isEmpty(transactionId) && StrUtil.isEmpty(outTradeNo)) { + return new AjaxResult().addError("out_trade_no transaction_id 不能同时为空"); + } + + Map params = OrderQueryModel.builder() + .service(ServiceEnum.QUERY.toString()) + .mch_id(unionPayBean.getMachId()) + .out_trade_no(outTradeNo) + .transaction_id(transactionId) + .nonce_str(WxPayKit.generateStr()) + .build() + .createSign(unionPayBean.getKey(), SignType.MD5); + + String xmlResult = UnionPayApi.execution(unionPayBean.getServerUrl(), params); + logger.info("xmlResult:" + xmlResult); + Map result = WxPayKit.xmlToMap(xmlResult); + if (!WxPayKit.verifyNotify(result, unionPayBean.getKey(), SignType.MD5)) { + return new AjaxResult().addError("签名异常"); + } + return new AjaxResult().success(result); + } catch (Exception e) { + e.printStackTrace(); + return new AjaxResult().addError(e.getMessage()); + } + } + + @RequestMapping(value = "/microPayReverse", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public AjaxResult microPayReverse(@RequestParam("outTradeNo") String outTradeNo) { + try { + + Map params = OrderQueryModel.builder() + .service(ServiceEnum.MICRO_PAY_REVERSE.toString()) + .mch_id(unionPayBean.getMachId()) + .out_trade_no(outTradeNo) + .nonce_str(WxPayKit.generateStr()) + .build() + .createSign(unionPayBean.getKey(), SignType.MD5); + + String xmlResult = UnionPayApi.execution(unionPayBean.getServerUrl(), params); + logger.info("xmlResult:" + xmlResult); + Map result = WxPayKit.xmlToMap(xmlResult); + return new AjaxResult().success(result); + } catch (Exception e) { + e.printStackTrace(); + return new AjaxResult().addError(e.getMessage()); + } + } + + @RequestMapping(value = "/refund", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public AjaxResult refund(@RequestParam(value = "transactionId", required = false) String transactionId, + @RequestParam(value = "outTradeNo", required = false) String outTradeNo, + @RequestParam(value = "totalFee") String totalFee, + @RequestParam(value = "refundFee") String refundFee) { + try { + + if (StrUtil.isEmpty(transactionId) && StrUtil.isEmpty(outTradeNo)) { + return new AjaxResult().addError("out_trade_no transaction_id 不能同时为空"); + } + + Map params = RefundModel.builder() + .service(ServiceEnum.REFUND.toString()) + .mch_id(unionPayBean.getMachId()) + .out_trade_no(outTradeNo) + .transaction_id(transactionId) + .out_refund_no(transactionId) + .total_fee(totalFee) + .refund_fee(refundFee) + .op_user_id(unionPayBean.getMachId()) + .nonce_str(WxPayKit.generateStr()) + .build() + .createSign(unionPayBean.getKey(), SignType.MD5); + + String xmlResult = UnionPayApi.execution(unionPayBean.getServerUrl(), params); + logger.info("xmlResult:" + xmlResult); + Map result = WxPayKit.xmlToMap(xmlResult); + return new AjaxResult().success(result); + } catch (Exception e) { + e.printStackTrace(); + return new AjaxResult().addError(e.getMessage()); + } + } + + @RequestMapping(value = "/queryRefund", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public AjaxResult queryRefund(@RequestParam(value = "transactionId", required = false) String transactionId, + @RequestParam(value = "outTradeNo", required = false) String outTradeNo, + @RequestParam(value = "outRefundNo", required = false) String outRefundNo, + @RequestParam(value = "refundId", required = false) String refundId) { + try { + + if (StrUtil.isEmpty(transactionId) && StrUtil.isEmpty(outTradeNo)) { + return new AjaxResult().addError("out_trade_no transaction_id 不能同时为空"); + } + + if (StrUtil.isEmpty(outRefundNo) && StrUtil.isEmpty(refundId)) { + return new AjaxResult().addError("out_refund_no refund_id 不能同时为空"); + } + + Map params = RefundQueryModel.builder() + .service(ServiceEnum.REFUND_QUERY.toString()) + .mch_id(unionPayBean.getMachId()) + .out_trade_no(outTradeNo) + .transaction_id(transactionId) + .out_refund_no(outRefundNo) + .refund_id(refundId) + .nonce_str(WxPayKit.generateStr()) + .build() + .createSign(unionPayBean.getKey(), SignType.MD5); + + String xmlResult = UnionPayApi.execution(unionPayBean.getServerUrl(), params); + logger.info("xmlResult:" + xmlResult); + Map result = WxPayKit.xmlToMap(xmlResult); + return new AjaxResult().success(result); + } catch (Exception e) { + e.printStackTrace(); + return new AjaxResult().addError(e.getMessage()); + } + } + + @RequestMapping(value = "/authCodeToOpenId", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public AjaxResult authCodeToOpenId(@RequestParam(value = "code") String code) { + try { + + Map params = AuthCodeToOpenIdModel.builder() + .service(ServiceEnum.AUTH_CODE_TO_OPENID.toString()) + .mch_id(unionPayBean.getMachId()) + .auth_code(code) + .nonce_str(WxPayKit.generateStr()) + .build() + .createSign(unionPayBean.getKey(), SignType.MD5); + + String xmlResult = UnionPayApi.execution(unionPayBean.getServerUrl(), params); + logger.info("xmlResult:" + xmlResult); + Map result = WxPayKit.xmlToMap(xmlResult); + return new AjaxResult().success(result); + } catch (Exception e) { + e.printStackTrace(); + return new AjaxResult().addError(e.getMessage()); + } + } + + @RequestMapping(value = "/native", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public AjaxResult nativePay(HttpServletRequest request, + @RequestParam(value = "totalFee", defaultValue = "1") String totalFee) { + try { + String notifyUrl = unionPayBean.getDomain().concat("/unionPay/payNotify"); + + String ip = IpKit.getRealIp(request); + if (StrUtil.isBlank(ip)) { + ip = "127.0.0.1"; + } + + Map params = UnifiedOrderModel.builder() + .service(ServiceEnum.NATIVE.toString()) + .mch_id(unionPayBean.getMachId()) + .out_trade_no(WxPayKit.generateStr()) + .body("IJPay 云闪付-扫码支付") + .attach("聚合支付 SDK") + .total_fee(totalFee) + .mch_create_ip(ip) + .notify_url(notifyUrl) + .nonce_str(WxPayKit.generateStr()) + .build() + .createSign(unionPayBean.getKey(), SignType.MD5); + + String xmlResult = UnionPayApi.execution(unionPayBean.getServerUrl(), params); + logger.info("xmlResult:" + xmlResult); + Map result = WxPayKit.xmlToMap(xmlResult); + return new AjaxResult().success(result); + } catch (Exception e) { + e.printStackTrace(); + return new AjaxResult().addError(e.getMessage()); + } + } + + @RequestMapping(value = "/wxJsPay", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public AjaxResult wxJsPay(HttpServletRequest request, + @RequestParam(value = "totalFee", defaultValue = "1") String totalFee, + @RequestParam(value = "openId") String openId) { + try { + + String notifyUrl = unionPayBean.getDomain().concat("/unionPay/payNotify"); + + String ip = IpKit.getRealIp(request); + if (ip.contains(",")) { + ip = ip.split(",")[0]; + } + if (StrUtil.isBlank(ip)) { + ip = "127.0.0.1"; + } + + Map params = UnifiedOrderModel.builder() + .service(ServiceEnum.WEI_XIN_JS_PAY.toString()) + .mch_id(unionPayBean.getMachId()) + .is_raw("1") + .out_trade_no(WxPayKit.generateStr()) + .body("IJPay 云闪付-微信公众号/小程序支付") + .sub_openid(openId) +// .sub_appid("appId") + .attach("聚合支付 SDK") + .total_fee(totalFee) + .mch_create_ip(ip) + .notify_url(notifyUrl) + .nonce_str(WxPayKit.generateStr()) + .build() + .createSign(unionPayBean.getKey(), SignType.MD5); + + System.out.println(params); + + String xmlResult = UnionPayApi.execution(unionPayBean.getServerUrl(), params); + logger.info("xmlResult:" + xmlResult); + Map result = WxPayKit.xmlToMap(xmlResult); + return new AjaxResult().success(result); + } catch (Exception e) { + e.printStackTrace(); + return new AjaxResult().addError(e.getMessage()); + } + } + + @RequestMapping(value = "/wxApp", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public AjaxResult wxApp(HttpServletRequest request, + @RequestParam(value = "totalFee", defaultValue = "1") String totalFee, + @RequestParam(value = "appId") String appId) { + try { + + String notifyUrl = unionPayBean.getDomain().concat("/unionPay/payNotify"); + + String ip = IpKit.getRealIp(request); + if (ip.contains(",")) { + ip = ip.split(",")[0]; + } + if (StrUtil.isBlank(ip)) { + ip = "127.0.0.1"; + } + + Map params = UnifiedOrderModel.builder() + .service(ServiceEnum.WEI_XIN_APP_PAY.toString()) + .mch_id(unionPayBean.getMachId()) + .appid(appId) + .out_trade_no(WxPayKit.generateStr()) + .body("IJPay 云闪付-微信 App 支付") + .attach("聚合支付 SDK") + .total_fee(totalFee) + .mch_create_ip(ip) + .notify_url(notifyUrl) + .nonce_str(WxPayKit.generateStr()) + .build() + .createSign(unionPayBean.getKey(), SignType.MD5); + + System.out.println(params); + + String xmlResult = UnionPayApi.execution(unionPayBean.getServerUrl(), params); + logger.info("xmlResult:" + xmlResult); + Map result = WxPayKit.xmlToMap(xmlResult); + if (!WxPayKit.verifyNotify(result, unionPayBean.getKey(), SignType.MD5)) { + return new AjaxResult().addError("签名异常"); + } + String status = result.get("status"); + String resultCode = result.get("result_code"); + if (!"0".equals(status) && !"0".equals(resultCode)) { + return new AjaxResult().addError(result.get("err_msg")); + } + + return new AjaxResult().success(result.get("pay_info")); + } catch (Exception e) { + e.printStackTrace(); + return new AjaxResult().addError(e.getMessage()); + } + } + + @RequestMapping(value = "/aliJsPay", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public AjaxResult aliJsPay(HttpServletRequest request, + @RequestParam(value = "totalFee", defaultValue = "1") String totalFee, + @RequestParam(value = "buyerLogonId", required = false) String buyerLogonId, + @RequestParam(value = "buyerId", required = false) String buyerId) { + try { + if (StrUtil.isEmpty(buyerLogonId) && StrUtil.isEmpty(buyerId)) { + return new AjaxResult().addError("buyer_logon_id buyer_id 不能同时为空"); + } + + String notifyUrl = unionPayBean.getDomain().concat("/unionPay/payNotify"); + + String ip = IpKit.getRealIp(request); + if (ip.contains(",")) { + ip = ip.split(",")[0]; + } + if (StrUtil.isBlank(ip)) { + ip = "127.0.0.1"; + } + + Map params = UnifiedOrderModel.builder() + .service(ServiceEnum.ALI_PAY_JS_PAY.toString()) + .mch_id(unionPayBean.getMachId()) + .out_trade_no(WxPayKit.generateStr()) + .body("IJPay 云闪付-支付宝服务窗口") + .attach("聚合支付 SDK") + .total_fee(totalFee) + .mch_create_ip(ip) + .notify_url(notifyUrl) + .nonce_str(WxPayKit.generateStr()) + .buyer_id(buyerId) + .buyer_logon_id(buyerLogonId) + .build() + .createSign(unionPayBean.getKey(), SignType.MD5); + + System.out.println(params); + + String xmlResult = UnionPayApi.execution(unionPayBean.getServerUrl(), params); + logger.info("xmlResult:" + xmlResult); + Map result = WxPayKit.xmlToMap(xmlResult); + return new AjaxResult().success(result); + } catch (Exception e) { + e.printStackTrace(); + return new AjaxResult().addError(e.getMessage()); + } + } + + + @RequestMapping(value = "/unionPayUserAuth", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public void unionPayUserAuth(HttpServletResponse response) throws IOException { + String notifyUrl = unionPayBean.getDomain().concat("/unionPay/callBack"); + String authUrl = UnionPayApi.buildAuthUrl(notifyUrl); + logger.info("authUrl:" + authUrl); + response.sendRedirect(authUrl); + } + + @RequestMapping(value = "/callBack", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public Map unionPayCall(HttpServletRequest request) { + Map params = new HashMap<>(); + Map requestParams = request.getParameterMap(); + 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] + ","; + } + params.put(name, valueStr); + } + return params; + } + + + @RequestMapping(value = "/unionJsPay", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public AjaxResult unionJsPay(HttpServletRequest request, + @RequestParam(value = "totalFee", defaultValue = "1") String totalFee, + @RequestParam(value = "userId", required = false) String userId) { + try { + + String notifyUrl = unionPayBean.getDomain().concat("/unionPay/payNotify"); + + String ip = IpKit.getRealIp(request); + if (ip.contains(",")) { + ip = ip.split(",")[0]; + } + if (StrUtil.isBlank(ip)) { + ip = "127.0.0.1"; + } + + Map params = UnifiedOrderModel.builder() + .service(ServiceEnum.UNION_JS_PAY.toString()) + .mch_id(unionPayBean.getMachId()) + .out_trade_no(WxPayKit.generateStr()) + .body("IJPay 云闪付-银联JS支付") + .user_id(userId) + .customer_ip(ip) + .attach("聚合支付 SDK") + .total_fee(totalFee) + .mch_create_ip(ip) + .notify_url(notifyUrl) + .nonce_str(WxPayKit.generateStr()) + .build() + .createSign(unionPayBean.getKey(), SignType.MD5); + + System.out.println(params); + + String xmlResult = UnionPayApi.execution(unionPayBean.getServerUrl(), params); + logger.info("xmlResult:" + xmlResult); + Map result = WxPayKit.xmlToMap(xmlResult); + return new AjaxResult().success(result); + } catch (Exception e) { + e.printStackTrace(); + return new AjaxResult().addError(e.getMessage()); + } + } + + @RequestMapping(value = "/billDownload", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public AjaxResult billDownload(@RequestParam(value = "billDate", defaultValue = "20200325") String billDate, + @RequestParam(value = "billType", defaultValue = "ALL") String billType) { + try { + + Map params = BillDownloadModel.builder() + .service(ServiceEnum.BILL_MERCHANT.toString()) + .bill_date(billDate) + .bill_type(billType) + .mch_id(unionPayBean.getMachId()) + .nonce_str(WxPayKit.generateStr()) + .build() + .createSign(unionPayBean.getKey(), SignType.MD5); + + System.out.println(params); + + String result = UnionPayApi.execution(unionPayBean.getServerUrl(), params); + logger.info("result:" + result); + return new AjaxResult().success(result); + } catch (Exception e) { + e.printStackTrace(); + return new AjaxResult().addError(e.getMessage()); + } + } + + /** + * 异步通知 + */ + @RequestMapping(value = "/payNotify", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public String payNotify(HttpServletRequest request) { + String xmlMsg = HttpKit.readData(request); + logger.info("支付通知=" + xmlMsg); + Map params = WxPayKit.xmlToMap(xmlMsg); + + String status = params.get("status"); + String returnCode = params.get("result_code"); + + logger.info(status + " " + returnCode); + + if ("0".equals(status) && "0".equals(returnCode)) { + // 注意重复通知的情况,同一订单号可能收到多次通知,请注意一定先判断订单状态 + // 注意此处签名方式需与统一下单的签名类型一致 + if (WxPayKit.verifyNotify(params, unionPayBean.getKey(), SignType.MD5)) { + logger.info("支付成功...."); + // 更新订单信息 + // 发送通知等 + return "success"; + } + } + return "fail"; + } +} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/wxpay/controller/AbstractWxPayApiController.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/wxpay/controller/AbstractWxPayApiController.java new file mode 100644 index 0000000..8d8fc32 --- /dev/null +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/wxpay/controller/AbstractWxPayApiController.java @@ -0,0 +1,16 @@ +package org.wfc.payment.pay.wxpay.controller; + + +import com.ijpay.wxpay.WxPayApiConfig; + +/** + * @author cyc + */ +public abstract class AbstractWxPayApiController { + /** + * 获取微信支付配置 + * + * @return {@link WxPayApiConfig} 微信支付配置 + */ + public abstract WxPayApiConfig getApiConfig(); +} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/wxpay/controller/WxPayController.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/wxpay/controller/WxPayController.java new file mode 100644 index 0000000..5319c8c --- /dev/null +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/wxpay/controller/WxPayController.java @@ -0,0 +1,964 @@ +package org.wfc.payment.pay.wxpay.controller; + +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; +import com.google.zxing.BarcodeFormat; +import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; +import com.ijpay.core.enums.SignType; +import com.ijpay.core.enums.TradeType; +import com.ijpay.core.kit.HttpKit; +import com.ijpay.core.kit.IpKit; +import com.ijpay.core.kit.QrCodeKit; +import com.ijpay.core.kit.RsaKit; +import com.ijpay.core.kit.WxPayKit; +import com.ijpay.wxpay.WxPayApi; +import com.ijpay.wxpay.WxPayApiConfig; +import com.ijpay.wxpay.WxPayApiConfigKit; +import com.ijpay.wxpay.model.GetTransferInfoModel; +import com.ijpay.wxpay.model.MicroPayModel; +import com.ijpay.wxpay.model.OrderQueryModel; +import com.ijpay.wxpay.model.ProfitSharingModel; +import com.ijpay.wxpay.model.ReceiverModel; +import com.ijpay.wxpay.model.RefundModel; +import com.ijpay.wxpay.model.RefundQueryModel; +import com.ijpay.wxpay.model.SendRedPackModel; +import com.ijpay.wxpay.model.TransferModel; +import com.ijpay.wxpay.model.UnifiedOrderModel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.util.ResourceUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.wfc.payment.domain.H5SceneInfo; +import org.wfc.payment.domain.WxPayBean; +import org.wfc.payment.domain.vo.AjaxResult; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * + *

微信支付 Demo

+ * + * @author cyc + */ +@Controller +@RequestMapping("/wxPay") +public class WxPayController extends AbstractWxPayApiController { + private final Logger log = LoggerFactory.getLogger(this.getClass()); + + @Autowired + WxPayBean wxPayBean; + + private String notifyUrl; + private String refundNotifyUrl; + private static final String USER_PAYING = "USERPAYING"; + + + @Override + public WxPayApiConfig getApiConfig() { + WxPayApiConfig apiConfig; + + try { + apiConfig = WxPayApiConfigKit.getApiConfig(wxPayBean.getAppId()); + } catch (Exception e) { + apiConfig = WxPayApiConfig.builder() + .appId(wxPayBean.getAppId()) + .mchId(wxPayBean.getMchId()) + .partnerKey(wxPayBean.getPartnerKey()) + .certPath(wxPayBean.getCertPath()) + .domain(wxPayBean.getDomain()) + .build(); + } + notifyUrl = apiConfig.getDomain().concat("/wxPay/payNotify"); + refundNotifyUrl = apiConfig.getDomain().concat("/wxPay/refundNotify"); + return apiConfig; + } + + @GetMapping("/test") + @ResponseBody + public WxPayBean test() { + return wxPayBean; + } + + @GetMapping("/getKey") + @ResponseBody + public String getKey() { + return WxPayApi.getSignKey(wxPayBean.getMchId(), wxPayBean.getPartnerKey(), SignType.MD5); + } + + /** + * 微信H5 支付 + * 注意:必须再web页面中发起支付且域名已添加到开发配置中 + */ + @RequestMapping(value = "/wapPay", method = {RequestMethod.POST, RequestMethod.GET}) + public void wapPay(HttpServletRequest request, HttpServletResponse response) throws IOException { + String ip = IpKit.getRealIp(request); + if (StrUtil.isBlank(ip)) { + ip = "127.0.0.1"; + } + + H5SceneInfo sceneInfo = new H5SceneInfo(); + + H5SceneInfo.H5 h5_info = new H5SceneInfo.H5(); + h5_info.setType("Wap"); + //此域名必须在商户平台--"产品中心"--"开发配置"中添加 + h5_info.setWap_url("https://gitee.com/javen205/IJPay"); + h5_info.setWap_name("IJPay VIP 充值"); + sceneInfo.setH5Info(h5_info); + + WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig(); + + Map params = UnifiedOrderModel + .builder() + .appid(wxPayApiConfig.getAppId()) + .mch_id(wxPayApiConfig.getMchId()) + .nonce_str(WxPayKit.generateStr()) + .body("IJPay 让支付触手可及-H5支付") + .attach("Node.js 版:https://gitee.com/javen205/TNWX") + .out_trade_no(WxPayKit.generateStr()) + .total_fee("1000") + .spbill_create_ip(ip) + .notify_url(notifyUrl) + .trade_type(TradeType.MWEB.getTradeType()) + .scene_info(JSON.toJSONString(sceneInfo)) + .build() + .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256); + + String xmlResult = WxPayApi.pushOrder(false, params); + log.info(xmlResult); + + Map result = WxPayKit.xmlToMap(xmlResult); + + String return_code = result.get("return_code"); + String return_msg = result.get("return_msg"); + if (!WxPayKit.codeIsOk(return_code)) { + throw new RuntimeException(return_msg); + } + String result_code = result.get("result_code"); + if (!WxPayKit.codeIsOk(result_code)) { + throw new RuntimeException(return_msg); + } + // 以下字段在return_code 和result_code都为SUCCESS的时候有返回 + + String prepayId = result.get("prepay_id"); + String webUrl = result.get("mweb_url"); + + log.info("prepay_id:" + prepayId + " mweb_url:" + webUrl); + response.sendRedirect(webUrl); + } + + /** + * 公众号支付 + */ + @RequestMapping(value = "/webPay", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public AjaxResult webPay(HttpServletRequest request, @RequestParam("total_fee") String totalFee) { + // openId,采用 网页授权获取 access_token API:SnsAccessTokenApi获取 + String openId = (String) request.getSession().getAttribute("openId"); + if (openId == null) { + openId = "11111111"; + } + + if (StrUtil.isEmpty(openId)) { + return new AjaxResult().addError("openId is null"); + } + if (StrUtil.isEmpty(totalFee)) { + return new AjaxResult().addError("请输入数字金额"); + } + String ip = IpKit.getRealIp(request); + if (StrUtil.isEmpty(ip)) { + ip = "127.0.0.1"; + } + + WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig(); + + Map params = UnifiedOrderModel + .builder() + .appid(wxPayApiConfig.getAppId()) + .mch_id(wxPayApiConfig.getMchId()) + .nonce_str(WxPayKit.generateStr()) + .body("IJPay 让支付触手可及-公众号支付") + .attach("Node.js 版:https://gitee.com/javen205/TNWX") + .out_trade_no(WxPayKit.generateStr()) + .total_fee("1000") + .spbill_create_ip(ip) + .notify_url(notifyUrl) + .trade_type(TradeType.JSAPI.getTradeType()) + .openid(openId) + .build() + .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256); + + String xmlResult = WxPayApi.pushOrder(false, params); + log.info(xmlResult); + + Map resultMap = WxPayKit.xmlToMap(xmlResult); + String returnCode = resultMap.get("return_code"); + String returnMsg = resultMap.get("return_msg"); + if (!WxPayKit.codeIsOk(returnCode)) { + return new AjaxResult().addError(returnMsg); + } + String resultCode = resultMap.get("result_code"); + if (!WxPayKit.codeIsOk(resultCode)) { + return new AjaxResult().addError(returnMsg); + } + + // 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回 + + String prepayId = resultMap.get("prepay_id"); + + Map packageParams = WxPayKit.prepayIdCreateSign(prepayId, wxPayApiConfig.getAppId(), + wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256); + + String jsonStr = JSON.toJSONString(packageParams); + return new AjaxResult().success(jsonStr); + } + + /** + * 扫码模式一 + */ + @RequestMapping(value = "/scanCode1", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public AjaxResult scanCode1(HttpServletRequest request, HttpServletResponse response, + @RequestParam("productId") String productId) { + try { + if (StrUtil.isBlank(productId)) { + return new AjaxResult().addError("productId is null"); + } + WxPayApiConfig config = WxPayApiConfigKit.getWxPayApiConfig(); + //获取扫码支付(模式一)url + String qrCodeUrl = WxPayKit.bizPayUrl(config.getPartnerKey(), config.getAppId(), config.getMchId(), productId); + log.info(qrCodeUrl); + //生成二维码保存的路径 + String name = "payQRCode1.png"; + log.info(ResourceUtils.getURL("classpath:").getPath()); + boolean encode = QrCodeKit.encode(qrCodeUrl, BarcodeFormat.QR_CODE, 3, ErrorCorrectionLevel.H, + "png", 200, 200, + ResourceUtils.getURL("classpath:").getPath().concat("static").concat(File.separator).concat(name)); + if (encode) { + //在页面上显示 + return new AjaxResult().success(name); + } + } catch (Exception e) { + e.printStackTrace(); + return new AjaxResult().addError("系统异常:" + e.getMessage()); + } + return null; + } + + /** + * 扫码支付模式一回调 + */ + @RequestMapping(value = "/scanCodeNotify", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public String scanCodeNotify(HttpServletRequest request, HttpServletResponse response) { + try { + String result = HttpKit.readData(request); + log.info("scanCodeNotify>>>" + result); + /** + * 获取返回的信息内容中各个参数的值 + */ + Map map = WxPayKit.xmlToMap(result); + for (String key : map.keySet()) { + log.info("key= " + key + " and value= " + map.get(key)); + } + + String appId = map.get("appid"); + String openId = map.get("openid"); + String mchId = map.get("mch_id"); + String isSubscribe = map.get("is_subscribe"); + String nonceStr = map.get("nonce_str"); + String productId = map.get("product_id"); + String sign = map.get("sign"); + + Map packageParams = new HashMap(6); + packageParams.put("appid", appId); + packageParams.put("openid", openId); + packageParams.put("mch_id", mchId); + packageParams.put("is_subscribe", isSubscribe); + packageParams.put("nonce_str", nonceStr); + packageParams.put("product_id", productId); + + WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig(); + + String packageSign = WxPayKit.createSign(packageParams, wxPayApiConfig.getPartnerKey(), SignType.MD5); + + String ip = IpKit.getRealIp(request); + if (StrUtil.isBlank(ip)) { + ip = "127.0.0.1"; + } + Map params = UnifiedOrderModel + .builder() + .appid(wxPayApiConfig.getAppId()) + .mch_id(wxPayApiConfig.getMchId()) + .nonce_str(WxPayKit.generateStr()) + .body("IJPay 让支付触手可及-扫码支付模式一") + .attach("Node.js 版:https://gitee.com/javen205/TNWX") + .out_trade_no(WxPayKit.generateStr()) + .total_fee("1") + .spbill_create_ip(ip) + .notify_url(notifyUrl) + .trade_type(TradeType.NATIVE.getTradeType()) + .openid(openId) + .build() + .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256); + String xmlResult = WxPayApi.pushOrder(false, params); + log.info("统一下单:" + xmlResult); + /** + * 发送信息给微信服务器 + */ + Map payResult = WxPayKit.xmlToMap(xmlResult); + String returnCode = payResult.get("return_code"); + String resultCode = payResult.get("result_code"); + if (WxPayKit.codeIsOk(returnCode) && WxPayKit.codeIsOk(resultCode)) { + // 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回 + String prepayId = payResult.get("prepay_id"); + + Map prepayParams = new HashMap(10); + prepayParams.put("return_code", "SUCCESS"); + prepayParams.put("appid", appId); + prepayParams.put("mch_id", mchId); + prepayParams.put("nonce_str", System.currentTimeMillis() + ""); + prepayParams.put("prepay_id", prepayId); + String prepaySign; + if (sign.equals(packageSign)) { + prepayParams.put("result_code", "SUCCESS"); + } else { + prepayParams.put("result_code", "FAIL"); + //result_code为FAIL时,添加该键值对,value值是微信告诉客户的信息 + prepayParams.put("err_code_des", "订单失效"); + } + prepaySign = WxPayKit.createSign(prepayParams, wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256); + prepayParams.put("sign", prepaySign); + String xml = WxPayKit.toXml(prepayParams); + log.error(xml); + return xml; + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 扫码支付模式二 + */ + @RequestMapping(value = "/scanCode2", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public AjaxResult scanCode2(HttpServletRequest request, HttpServletResponse response, + @RequestParam("total_fee") String totalFee) { + + if (StrUtil.isBlank(totalFee)) { + return new AjaxResult().addError("支付金额不能为空"); + } + + String ip = IpKit.getRealIp(request); + if (StrUtil.isBlank(ip)) { + ip = "127.0.0.1"; + } + WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig(); + + Map params = UnifiedOrderModel + .builder() + .appid(wxPayApiConfig.getAppId()) + .mch_id(wxPayApiConfig.getMchId()) + .nonce_str(WxPayKit.generateStr()) + .body("IJPay 让支付触手可及-扫码支付模式二") + .attach("Node.js 版:https://gitee.com/javen205/TNWXX") + .out_trade_no(WxPayKit.generateStr()) + .total_fee("1") + .spbill_create_ip(ip) + .notify_url(notifyUrl) + .trade_type(TradeType.NATIVE.getTradeType()) + .build() + .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256); + + String xmlResult = WxPayApi.pushOrder(false, params); + log.info("统一下单:" + xmlResult); + + Map result = WxPayKit.xmlToMap(xmlResult); + + String returnCode = result.get("return_code"); + String returnMsg = result.get("return_msg"); + System.out.println(returnMsg); + if (!WxPayKit.codeIsOk(returnCode)) { + return new AjaxResult().addError("error:" + returnMsg); + } + String resultCode = result.get("result_code"); + if (!WxPayKit.codeIsOk(resultCode)) { + return new AjaxResult().addError("error:" + returnMsg); + } + //生成预付订单success + + String qrCodeUrl = result.get("code_url"); + String name = "payQRCode2.png"; + + boolean encode = QrCodeKit.encode(qrCodeUrl, BarcodeFormat.QR_CODE, 3, ErrorCorrectionLevel.H, "png", 200, 200, + request.getSession().getServletContext().getRealPath("/") + File.separator + name); + if (encode) { + //在页面上显示 + return new AjaxResult().success(name); + } + return null; + } + + /** + * 刷卡支付 + */ + @RequestMapping(value = "/microPay", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public AjaxResult microPay(HttpServletRequest request, HttpServletResponse response) { + String authCode = request.getParameter("auth_code"); + String totalFee = request.getParameter("total_fee"); + if (StrUtil.isBlank(totalFee)) { + return new AjaxResult().addError("支付金额不能为空"); + } + if (StrUtil.isBlank(authCode)) { + return new AjaxResult().addError("auth_code参数错误"); + } + String ip = IpKit.getRealIp(request); + if (StrUtil.isBlank(ip)) { + ip = "127.0.0.1"; + } + WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig(); + + Map params = MicroPayModel.builder() + .appid(wxPayApiConfig.getAppId()) + .mch_id(wxPayApiConfig.getMchId()) + .nonce_str(WxPayKit.generateStr()) + .body("IJPay 让支付触手可及-刷卡支付") + .attach("Node.js 版:https://gitee.com/javen205/TNWXX") + .out_trade_no(WxPayKit.generateStr()) + .total_fee("1") + .spbill_create_ip(ip) + .auth_code(authCode) + .build() + .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256); + + String xmlResult = WxPayApi.microPay(false, params); + //同步返回结果 + log.info("xmlResult:" + xmlResult); + Map result = WxPayKit.xmlToMap(xmlResult); + String returnCode = result.get("return_code"); + String returnMsg = result.get("return_msg"); + if (!WxPayKit.codeIsOk(returnCode)) { + //通讯失败 + String errCode = result.get("err_code"); + if (StrUtil.isNotBlank(errCode)) { + //用户支付中,需要输入密码 + if (USER_PAYING.equals(errCode)) { + //等待5秒后调用【查询订单API】 + } + } + log.info("提交刷卡支付失败>>" + xmlResult); + return new AjaxResult().addError(returnMsg); + } + + String resultCode = result.get("result_code"); + if (!WxPayKit.codeIsOk(resultCode)) { + log.info("支付失败>>" + xmlResult); + String errCodeDes = result.get("err_code_des"); + return new AjaxResult().addError(errCodeDes); + } + //支付成功 + return new AjaxResult().success(xmlResult); + } + + /** + * 微信APP支付 + */ + @RequestMapping(value = "/appPay", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public AjaxResult appPay(HttpServletRequest request) { + + String ip = IpKit.getRealIp(request); + if (StrUtil.isBlank(ip)) { + ip = "127.0.0.1"; + } + + WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig(); + + Map params = UnifiedOrderModel + .builder() + .appid(wxPayApiConfig.getAppId()) + .mch_id(wxPayApiConfig.getMchId()) + .nonce_str(WxPayKit.generateStr()) + .body("IJPay 让支付触手可及-App支付") + .attach("Node.js 版:https://gitee.com/javen205/TNWXX") + .out_trade_no(WxPayKit.generateStr()) + .total_fee("1000") + .spbill_create_ip(ip) + .notify_url(notifyUrl) + .trade_type(TradeType.APP.getTradeType()) + .build() + .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256); + + String xmlResult = WxPayApi.pushOrder(false, params); + + log.info(xmlResult); + Map result = WxPayKit.xmlToMap(xmlResult); + + String returnCode = result.get("return_code"); + String returnMsg = result.get("return_msg"); + if (!WxPayKit.codeIsOk(returnCode)) { + return new AjaxResult().addError(returnMsg); + } + String resultCode = result.get("result_code"); + if (!WxPayKit.codeIsOk(resultCode)) { + return new AjaxResult().addError(returnMsg); + } + // 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回 + String prepayId = result.get("prepay_id"); + + Map packageParams = WxPayKit.appPrepayIdCreateSign(wxPayApiConfig.getAppId(), wxPayApiConfig.getMchId(), prepayId, + wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256); + + String jsonStr = JSON.toJSONString(packageParams); + log.info("返回apk的参数:" + jsonStr); + return new AjaxResult().success(jsonStr); + } + + /** + * 微信小程序支付 + */ + @RequestMapping(value = "/miniAppPay", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public AjaxResult miniAppPay(HttpServletRequest request) { + //需要通过授权来获取openId + String openId = (String) request.getSession().getAttribute("openId"); + + String ip = IpKit.getRealIp(request); + if (StrUtil.isBlank(ip)) { + ip = "127.0.0.1"; + } + + WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig(); + + Map params = UnifiedOrderModel + .builder() + .appid(wxPayApiConfig.getAppId()) + .mch_id(wxPayApiConfig.getMchId()) + .nonce_str(WxPayKit.generateStr()) + .body("IJPay 让支付触手可及-小程序支付") + .attach("Node.js 版:https://gitee.com/javen205/TNWXX") + .out_trade_no(WxPayKit.generateStr()) + .total_fee("1000") + .spbill_create_ip(ip) + .notify_url(notifyUrl) + .trade_type(TradeType.JSAPI.getTradeType()) + .openid(openId) + .build() + .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256); + + String xmlResult = WxPayApi.pushOrder(false, params); + + log.info(xmlResult); + Map result = WxPayKit.xmlToMap(xmlResult); + + String returnCode = result.get("return_code"); + String returnMsg = result.get("return_msg"); + if (!WxPayKit.codeIsOk(returnCode)) { + return new AjaxResult().addError(returnMsg); + } + String resultCode = result.get("result_code"); + if (!WxPayKit.codeIsOk(resultCode)) { + return new AjaxResult().addError(returnMsg); + } + // 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回 + String prepayId = result.get("prepay_id"); + Map packageParams = WxPayKit.miniAppPrepayIdCreateSign(wxPayApiConfig.getAppId(), prepayId, + wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256); + String jsonStr = JSON.toJSONString(packageParams); + log.info("小程序支付的参数:" + jsonStr); + return new AjaxResult().success(jsonStr); + } + + @RequestMapping(value = "/queryOrder", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public String queryOrder(@RequestParam(value = "transactionId", required = false) String transactionId, @RequestParam(value = "outTradeNo", required = false) String outTradeNo) { + try { + WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig(); + + Map params = OrderQueryModel.builder() + .appid(wxPayApiConfig.getAppId()) + .mch_id(wxPayApiConfig.getMchId()) + .transaction_id(transactionId) + .out_trade_no(outTradeNo) + .nonce_str(WxPayKit.generateStr()) + .build() + .createSign(wxPayApiConfig.getPartnerKey(), SignType.MD5); + log.info("请求参数:{}", WxPayKit.toXml(params)); + String query = WxPayApi.orderQuery(params); + log.info("查询结果: {}", query); + return query; + } catch (Exception e) { + e.printStackTrace(); + return "系统错误"; + } + } + + /** + * 企业付款到零钱 + */ + @RequestMapping(value = "/transfer", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public String transfer(HttpServletRequest request, @RequestParam("openId") String openId) { + + String ip = IpKit.getRealIp(request); + if (StrUtil.isBlank(ip)) { + ip = "127.0.0.1"; + } + + WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig(); + + Map params = TransferModel.builder() + .mch_appid(wxPayApiConfig.getAppId()) + .mchid(wxPayApiConfig.getMchId()) + .nonce_str(WxPayKit.generateStr()) + .partner_trade_no(WxPayKit.generateStr()) + .openid(openId) + .check_name("NO_CHECK") + .amount("100") + .desc("IJPay 让支付触手可及-企业付款") + .spbill_create_ip(ip) + .build() + .createSign(wxPayApiConfig.getPartnerKey(), SignType.MD5, false); + + // 提现 + String transfers = WxPayApi.transfers(params, wxPayApiConfig.getCertPath(), wxPayApiConfig.getMchId()); + log.info("提现结果:" + transfers); + Map map = WxPayKit.xmlToMap(transfers); + String returnCode = map.get("return_code"); + String resultCode = map.get("result_code"); + if (WxPayKit.codeIsOk(returnCode) && WxPayKit.codeIsOk(resultCode)) { + // 提现成功 + } else { + // 提现失败 + } + return transfers; + } + + /** + * 查询企业付款到零钱 + */ + @RequestMapping(value = "/transferInfo", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public String transferInfo(@RequestParam("partner_trade_no") String partnerTradeNo) { + try { + WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig(); + + Map params = GetTransferInfoModel.builder() + .nonce_str(WxPayKit.generateStr()) + .partner_trade_no(partnerTradeNo) + .mch_id(wxPayApiConfig.getMchId()) + .appid(wxPayApiConfig.getAppId()) + .build() + .createSign(wxPayApiConfig.getPartnerKey(), SignType.MD5, false); + + return WxPayApi.getTransferInfo(params, wxPayApiConfig.getCertPath(), wxPayApiConfig.getMchId()); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 获取RSA加密公钥 + */ + @RequestMapping(value = "/getPublicKey", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public String getPublicKey() { + try { + WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig(); + + Map params = new HashMap(4); + params.put("mch_id", wxPayApiConfig.getMchId()); + params.put("nonce_str", String.valueOf(System.currentTimeMillis())); + params.put("sign_type", "MD5"); + String createSign = WxPayKit.createSign(params, wxPayApiConfig.getPartnerKey(), SignType.MD5); + params.put("sign", createSign); + return WxPayApi.getPublicKey(params, wxPayApiConfig.getCertPath(), wxPayApiConfig.getMchId()); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 企业付款到银行卡 + */ + @RequestMapping(value = "/payBank", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public String payBank() { + try { + WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig(); + + //通过WxPayApi.getPublicKey接口获取RSA加密公钥 + //假设获取到的RSA加密公钥为PUBLIC_KEY(PKCS#8格式) + final String PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6Bl76IwSvBTiibZ+CNRUA6BfahMshZ0WJpHD1GpmvcQjeN6Yrv6c9eIl6gB4nU3isN7bn+LmoVTpH1gHViaV2YyG/zXj4z4h7r+V+ezesMqqorEg38BCNUHNmhnw4/C0I4gBAQ4x0SJOGnfKGZKR9yzvbkJtvEn732JcEZCbdTZmaxkwlenXvM+mStcJaxBCB/h5xJ5VOF5nDbTPzLphIpzddr3zx/Jxjna9QB1v/YSKYXn+iuwruNUXGCvvxBWaBGKrjOdRTRy9adWOgNmtuYDQJ2YOfG8PtPe06ELKjmr2CfaAGrKKUroyaGvy3qxAV0PlT+UQ4ADSXWt/zl0o5wIDAQAB"; + + Map params = new HashMap(10); + params.put("mch_id", wxPayApiConfig.getMchId()); + params.put("partner_trade_no", System.currentTimeMillis() + ""); + params.put("nonce_str", System.currentTimeMillis() + ""); + //收款方银行卡号 + params.put("enc_bank_no", RsaKit.encryptByPublicKeyByWx("银行卡号", PUBLIC_KEY)); + //收款方用户名 + params.put("enc_true_name", RsaKit.encryptByPublicKeyByWx("银行卡持有人姓名", PUBLIC_KEY)); + //收款方开户行 + params.put("bank_code", "1001"); + params.put("amount", "1"); + params.put("desc", "IJPay 让支付触手可及-付款到银行卡"); + params.put("sign", WxPayKit.createSign(params, wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256)); + return WxPayApi.payBank(params, wxPayApiConfig.getCertPath(), wxPayApiConfig.getMchId()); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 查询企业付款到银行 + */ + @RequestMapping(value = "/queryBank", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public String queryBank(@RequestParam("partner_trade_no") String partnerTradeNo) { + try { + WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig(); + + Map params = new HashMap(4); + params.put("mch_id", wxPayApiConfig.getMchId()); + params.put("partner_trade_no", partnerTradeNo); + params.put("nonce_str", System.currentTimeMillis() + ""); + params.put("sign", WxPayKit.createSign(params, wxPayApiConfig.getPartnerKey(), SignType.MD5)); + return WxPayApi.queryBank(params, wxPayApiConfig.getCertPath(), wxPayApiConfig.getMchId()); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 添加分账接收方 + */ + @RequestMapping(value = "/profitSharingAddReceiver", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public String profitSharingAddReceiver() { + try { + ReceiverModel receiver = ReceiverModel.builder() + .type("PERSONAL_OPENID") + .account("openid") + .relation_type("PARTNER") + .build(); + + Map params = ProfitSharingModel.builder() + .mch_id(wxPayBean.getMchId()) + .appid(wxPayBean.getAppId()) + .nonce_str(WxPayKit.generateStr()) + .receiver(JSON.toJSONString(receiver)) + .build() + .createSign(wxPayBean.getPartnerKey(), SignType.HMACSHA256); + log.info("请求参数:{}", WxPayKit.toXml(params)); + String result = WxPayApi.profitSharingAddReceiver(params); + log.info("请求结果:{}", result); + return JSON.toJSONString(WxPayKit.xmlToMap(result)); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 请求单次分账 + */ + @RequestMapping(value = "/profitSharing", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public String profitSharing(@RequestParam(value = "transactionId") String transactionId) { + List list = new ArrayList<>(); + + list.add(ReceiverModel.builder() + .type("PERSONAL_OPENID") + .account("openid") + .amount(66) + .description("IJPay 分账") + .build()); + + Map params = ProfitSharingModel.builder() + .mch_id(wxPayBean.getMchId()) + .appid(wxPayBean.getAppId()) + .nonce_str(WxPayKit.generateStr()) + .transaction_id(transactionId) + .out_order_no(WxPayKit.generateStr()) + .receivers(JSON.toJSONString(list)) + .build() + .createSign(wxPayBean.getPartnerKey(), SignType.HMACSHA256); + + log.info("请求参数:{}", WxPayKit.toXml(params)); + String result = WxPayApi.profitSharing(params, wxPayBean.getCertPath(), wxPayBean.getMchId()); + log.info("请求结果:{}", result); + return JSON.toJSONString(WxPayKit.xmlToMap(result)); + } + + + /** + * 微信退款 + */ + @RequestMapping(value = "/refund", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public String refund(@RequestParam(value = "transactionId", required = false) String transactionId, + @RequestParam(value = "outTradeNo", required = false) String outTradeNo) { + try { + log.info("transactionId: {} outTradeNo:{}", transactionId, outTradeNo); + + if (StrUtil.isBlank(outTradeNo) && StrUtil.isBlank(transactionId)) { + return "transactionId、out_trade_no二选一"; + } + WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig(); + + Map params = RefundModel.builder() + .appid(wxPayApiConfig.getAppId()) + .mch_id(wxPayApiConfig.getMchId()) + .nonce_str(WxPayKit.generateStr()) + .transaction_id(transactionId) + .out_trade_no(outTradeNo) + .out_refund_no(WxPayKit.generateStr()) + .total_fee("1") + .refund_fee("1") + .notify_url(refundNotifyUrl) + .build() + .createSign(wxPayApiConfig.getPartnerKey(), SignType.MD5); + String refundStr = WxPayApi.orderRefund(false, params, wxPayApiConfig.getCertPath(), wxPayApiConfig.getMchId()); + log.info("refundStr: {}", refundStr); + return refundStr; + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 微信退款查询 + */ + @RequestMapping(value = "/refundQuery", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public String refundQuery(@RequestParam("transactionId") String transactionId, + @RequestParam("out_trade_no") String outTradeNo, + @RequestParam("out_refund_no") String outRefundNo, + @RequestParam("refund_id") String refundId) { + + WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig(); + + Map params = RefundQueryModel.builder() + .appid(wxPayApiConfig.getAppId()) + .mch_id(wxPayApiConfig.getMchId()) + .nonce_str(WxPayKit.generateStr()) + .transaction_id(transactionId) + .out_trade_no(outTradeNo) + .out_refund_no(outRefundNo) + .refund_id(refundId) + .build() + .createSign(wxPayApiConfig.getPartnerKey(), SignType.MD5); + + return WxPayApi.orderRefundQuery(false, params); + } + + /** + * 退款通知 + */ + @RequestMapping(value = "/refundNotify", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public String refundNotify(HttpServletRequest request) { + String xmlMsg = HttpKit.readData(request); + log.info("退款通知=" + xmlMsg); + Map params = WxPayKit.xmlToMap(xmlMsg); + + String returnCode = params.get("return_code"); + // 注意重复通知的情况,同一订单号可能收到多次通知,请注意一定先判断订单状态 + if (WxPayKit.codeIsOk(returnCode)) { + String reqInfo = params.get("req_info"); + String decryptData = WxPayKit.decryptData(reqInfo, WxPayApiConfigKit.getWxPayApiConfig().getPartnerKey()); + log.info("退款通知解密后的数据=" + decryptData); + // 更新订单信息 + // 发送通知等 + Map xml = new HashMap(2); + xml.put("return_code", "SUCCESS"); + xml.put("return_msg", "OK"); + return WxPayKit.toXml(xml); + } + return null; + } + + @RequestMapping(value = "/sendRedPack", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public String sendRedPack(HttpServletRequest request, @RequestParam("openId") String openId) { + try { + String ip = IpKit.getRealIp(request); + if (StrUtil.isBlank(ip)) { + ip = "127.0.0.1"; + } + + WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig(); + + Map params = SendRedPackModel.builder() + .nonce_str(WxPayKit.generateStr()) + .mch_billno(WxPayKit.generateStr()) + .mch_id(wxPayApiConfig.getMchId()) + .wxappid(wxPayApiConfig.getAppId()) + .send_name("IJPay 红包测试") + .re_openid(openId) + .total_amount("1000") + .total_num("1") + .wishing("感谢您使用 IJPay") + .client_ip(ip) + .act_name("感恩回馈活动") + .remark("点 start 送红包,快来抢!") + .build() + .createSign(wxPayApiConfig.getPartnerKey(), SignType.MD5); + String result = WxPayApi.sendRedPack(params, wxPayApiConfig.getCertPath(), wxPayApiConfig.getMchId()); + System.out.println("发送红包结果:" + result); + Map map = WxPayKit.xmlToMap(result); + return JSON.toJSONString(map); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 异步通知 + */ + @RequestMapping(value = "/payNotify", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public String payNotify(HttpServletRequest request) { + String xmlMsg = HttpKit.readData(request); + log.info("支付通知=" + xmlMsg); + Map params = WxPayKit.xmlToMap(xmlMsg); + + String returnCode = params.get("return_code"); + + // 注意重复通知的情况,同一订单号可能收到多次通知,请注意一定先判断订单状态 + // 注意此处签名方式需与统一下单的签名类型一致 + if (WxPayKit.verifyNotify(params, WxPayApiConfigKit.getWxPayApiConfig().getPartnerKey(), SignType.HMACSHA256)) { + if (WxPayKit.codeIsOk(returnCode)) { + // 更新订单信息 + // 发送通知等 + Map xml = new HashMap(2); + xml.put("return_code", "SUCCESS"); + xml.put("return_msg", "OK"); + return WxPayKit.toXml(xml); + } + } + return null; + } +} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/wxpay/controller/WxPayV3Controller.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/wxpay/controller/WxPayV3Controller.java new file mode 100644 index 0000000..3adec95 --- /dev/null +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/pay/wxpay/controller/WxPayV3Controller.java @@ -0,0 +1,982 @@ +package org.wfc.payment.pay.wxpay.controller; + +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.file.FileWriter; +import cn.hutool.core.util.HexUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.crypto.SecureUtil; +import cn.hutool.crypto.SmUtil; +import cn.hutool.crypto.asymmetric.SM2; +import cn.hutool.http.ContentType; +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.ijpay.core.IJPayHttpResponse; +import com.ijpay.core.enums.AuthTypeEnum; +import com.ijpay.core.enums.RequestMethodEnum; +import com.ijpay.core.kit.AesUtil; +import com.ijpay.core.kit.HttpKit; +import com.ijpay.core.kit.PayKit; +import com.ijpay.core.kit.WxPayKit; +import com.ijpay.core.utils.DateTimeZoneUtil; +import com.ijpay.wxpay.WxPayApi; +import com.ijpay.wxpay.enums.WxDomainEnum; +import com.ijpay.wxpay.enums.v3.Apply4SubApiEnum; +import com.ijpay.wxpay.enums.v3.BasePayApiEnum; +import com.ijpay.wxpay.enums.v3.CertAlgorithmTypeEnum; +import com.ijpay.wxpay.enums.v3.ComplaintsApiEnum; +import com.ijpay.wxpay.enums.v3.OtherApiEnum; +import com.ijpay.wxpay.enums.v3.PayGiftActivityApiEnum; +import com.ijpay.wxpay.enums.v3.PayScoreApiEnum; +import com.ijpay.wxpay.enums.v3.TransferApiEnum; +import com.ijpay.wxpay.model.v3.Amount; +import com.ijpay.wxpay.model.v3.BatchTransferModel; +import com.ijpay.wxpay.model.v3.H5Info; +import com.ijpay.wxpay.model.v3.Payer; +import com.ijpay.wxpay.model.v3.RefundAmount; +import com.ijpay.wxpay.model.v3.RefundGoodsDetail; +import com.ijpay.wxpay.model.v3.RefundModel; +import com.ijpay.wxpay.model.v3.SceneInfo; +import com.ijpay.wxpay.model.v3.TransferDetailInput; +import com.ijpay.wxpay.model.v3.UnifiedOrderModel; +import org.bouncycastle.crypto.engines.SM2Engine; +import org.bouncycastle.crypto.signers.PlainDSAEncoding; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.wfc.payment.domain.WxPayV3Bean; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * + *

微信支付 v3 接口示例

+ * + * @author cyc + */ +@Controller +@RequestMapping("/v3") +public class WxPayV3Controller { + private final Logger log = LoggerFactory.getLogger(this.getClass()); + private final static int OK = 200; + + @Resource + WxPayV3Bean wxPayV3Bean; + + String serialNo; + String platSerialNo; + + + @RequestMapping("") + @ResponseBody + public String index() { + log.info(wxPayV3Bean.toString()); + try { + String classPath = "classpath:/dev/apiclient_key.pem"; + String v3 = "classpath:/dev/wxpay_v3.properties"; + String absolutePath = PayKit.getAbsolutePath(classPath); + log.info("absolutePath:{}", absolutePath); + String certFileContent = PayKit.getCertFileContent(classPath); + log.info("classPath content:{}", certFileContent); + InputStream inputStream = PayKit.getCertFileInputStream(v3); + if (null != inputStream) { + ByteArrayOutputStream result = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int length; + while ((length = inputStream.read(buffer)) != -1) { + result.write(buffer, 0, length); + } + String str = result.toString(); + log.info("file content:{}", str); + } + } catch (Exception e) { + log.error("文件不存在", e); + } + return ("欢迎使用 的微信支付 Api-v3"); + } + + @RequestMapping("/getSerialNumber") + @ResponseBody + public String serialNumber() { + return getSerialNumber(); + } + + @RequestMapping("/getPlatSerialNumber") + @ResponseBody + public String platSerialNumber() { + return getPlatSerialNumber(); + } + + private String getSerialNumber() { + if (StrUtil.isEmpty(serialNo)) { + // 获取证书序列号 + X509Certificate certificate = PayKit.getCertificate(wxPayV3Bean.getCertPath()); + if (null != certificate) { + serialNo = certificate.getSerialNumber().toString(16).toUpperCase(); + // 提前两天检查证书是否有效 + boolean isValid = PayKit.checkCertificateIsValid(certificate, wxPayV3Bean.getMchId(), -2); + log.info("证书是否可用 {} 证书有效期为 {}", isValid, DateUtil.format(certificate.getNotAfter(), DatePattern.NORM_DATETIME_PATTERN)); + } +// System.out.println("输出证书信息:\n" + certificate.toString()); +// // 输出关键信息,截取部分并进行标记 +// System.out.println("证书序列号:" + certificate.getSerialNumber().toString(16)); +// System.out.println("版本号:" + certificate.getVersion()); +// System.out.println("签发者:" + certificate.getIssuerDN()); +// System.out.println("有效起始日期:" + certificate.getNotBefore()); +// System.out.println("有效终止日期:" + certificate.getNotAfter()); +// System.out.println("主体名:" + certificate.getSubjectDN()); +// System.out.println("签名算法:" + certificate.getSigAlgName()); +// System.out.println("签名:" + certificate.getSignature().toString()); + } + System.out.println("serialNo:" + serialNo); + return serialNo; + } + + private String getPlatSerialNumber() { + if (StrUtil.isEmpty(platSerialNo)) { + // 获取平台证书序列号 + X509Certificate certificate = PayKit.getCertificate(FileUtil.getInputStream(wxPayV3Bean.getPlatformCertPath())); + platSerialNo = certificate.getSerialNumber().toString(16).toUpperCase(); + } + System.out.println("platSerialNo:" + platSerialNo); + return platSerialNo; + } + + private String savePlatformCert(String associatedData, String nonce, String cipherText, String algorithm, String certPath) { + try { + String key3 = wxPayV3Bean.getApiKey3(); + String publicKey; + if (StrUtil.equals(algorithm, AuthTypeEnum.SM2.getPlatformCertAlgorithm())) { + publicKey = PayKit.sm4DecryptToString(key3, cipherText, nonce, associatedData); + } else { + AesUtil aesUtil = new AesUtil(wxPayV3Bean.getApiKey3().getBytes(StandardCharsets.UTF_8)); + // 平台证书密文解密 + // encrypt_certificate 中的 associated_data nonce ciphertext + publicKey = aesUtil.decryptToString( + associatedData.getBytes(StandardCharsets.UTF_8), + nonce.getBytes(StandardCharsets.UTF_8), + cipherText + ); + } + if (StrUtil.isNotEmpty(publicKey)) { + // 保存证书 + FileWriter writer = new FileWriter(certPath); + writer.write(publicKey); + // 获取平台证书序列号 + X509Certificate certificate = PayKit.getCertificate(new ByteArrayInputStream(publicKey.getBytes())); + return certificate.getSerialNumber().toString(16).toUpperCase(); + } + return ""; + } catch (Exception e) { + log.error("保存平台证书异常", e); + return e.getMessage(); + } + } + + + @RequestMapping("/platformCert") + @ResponseBody + public String platformCert() { + try { + String associatedData = "certificate"; + String nonce = "80d28946a64a"; + String cipherText = "DwAqW4+4TeUaOEylfKEXhw+XqGh/YTRhUmLw/tBfQ5nM9DZ9d+9aGEghycwV1jwo52vXb/t6ueBvBRHRIW5JgDRcXmTHw9IMTrIK6HxTt2qiaGTWJU9whsF+GGeQdA7gBCHZm3AJUwrzerAGW1mclXBTvXqaCl6haE7AOHJ2g4RtQThi3nxOI63/yc3WaiAlSR22GuCpy6wJBfljBq5Bx2xXDZXlF2TNbDIeodiEnJEG2m9eBWKuvKPyUPyClRXG1fdOkKnCZZ6u+ipb4IJx28n3MmhEtuc2heqqlFUbeONaRpXv6KOZmH/IdEL6nqNDP2D7cXutNVCi0TtSfC7ojnO/+PKRu3MGO2Z9q3zyZXmkWHCSms/C3ACatPUKHIK+92MxjSQDc1E/8faghTc9bDgn8cqWpVKcL3GHK+RfuYKiMcdSkUDJyMJOwEXMYNUdseQMJ3gL4pfxuQu6QrVvJ17q3ZjzkexkPNU4PNSlIBJg+KX61cyBTBumaHy/EbHiP9V2GeM729a0h5UYYJVedSo1guIGjMZ4tA3WgwQrlpp3VAMKEBLRJMcnHd4pH5YQ/4hiUlHGEHttWtnxKFwnJ6jHr3OmFLV1FiUUOZEDAqR0U1KhtGjOffnmB9tymWF8FwRNiH2Tee/cCDBaHhNtfPI5129SrlSR7bZc+h7uzz9z+1OOkNrWHzAoWEe3XVGKAywpn5HGbcL+9nsEVZRJLvV7aOxAZBkxhg8H5Fjt1ioTJL+qXgRzse1BX1iiwfCR0fzEWT9ldDTDW0Y1b3tb419MhdmTQB5FsMXYOzqp5h+Tz1FwEGsa6TJsmdjJQSNz+7qPSg5D6C2gc9/6PkysSu/6XfsWXD7cQkuZ+TJ/Xb6Q1Uu7ZB90SauA8uPQUIchW5zQ6UfK5dwMkOuEcE/141/Aw2rlDqjtsE17u1dQ6TCax/ZQTDQ2MDUaBPEaDIMPcgL7fCeijoRgovkBY92m86leZvQ+HVbxlFx5CoPhz4a81kt9XJuEYOztSIKlm7QNfW0BvSUhLmxDNCjcxqwyydtKbLzA+EBb2gG4ORiH8IOTbV0+G4S6BqetU7RrO+/nKt21nXVqXUmdkhkBakLN8FUcHygyWnVxbA7OI2RGnJJUnxqHd3kTbzD5Wxco4JIQsTOV6KtO5c960oVYUARZIP1SdQhqwELm27AktEN7kzg/ew/blnTys/eauGyw78XCROb9F1wbZBToUZ7L+8/m/2tyyyqNid+sC9fYqJoIOGfFOe6COWzTI/XPytCHwgHeUxmgk7NYfU0ukR223RPUOym6kLzSMMBKCivnNg68tbLRJHEOpQTXFBaFFHt2qpceJpJgw5sKFqx3eQnIFuyvA1i8s2zKLhULZio9hpsDJQREOcNeHVjEZazdCGnbe3Vjg7uqOoVHdE/YbNzJNQEsB3/erYJB+eGzyFwFmdAHenG5RE6FhCutjszwRiSvW9F7wvRK36gm7NnVJZkvlbGwh0UHr0pbcrOmxT81xtNSvMzT0VZNLTUX2ur3AGLwi2ej8BIC0H41nw4ToxTnwtFR1Xy55+pUiwpB7JzraA08dCXdFdtZ72Tw/dNBy5h1P7EtQYiKzXp6rndfOEWgNOsan7e1XRpCnX7xoAkdPvy40OuQ5gNbDKry5gVDEZhmEk/WRuGGaX06CG9m7NfErUsnQYrDJVjXWKYuARd9R7W0aa5nUXqz/Pjul/LAatJgWhZgFBGXhNr9iAoade/0FPpBj0QWa8SWqKYKiOqXqhfhppUq35FIa0a1Vvxcn3E38XYpVZVTDEXcEcD0RLCu/ezdOa6vRcB7hjgXFIRZQAka0aXnQxwOZwE2Rt3yWXqc+Q1ah2oOrg8Lg3ETc644X9QP4FxOtDwz/A=="; + String algorithm = "AEAD_AES_256_GCM"; + return savePlatformCert(associatedData, nonce, cipherText, algorithm, wxPayV3Bean.getPlatformCertPath()); + } catch (Exception e) { + log.error("保存平台证书异常", e); + return e.getMessage(); + } + } + + @RequestMapping("/smPlatformCert") + @ResponseBody + public String smPlatformCert() { + try { + String associatedData = "certificate"; + String nonce = ""; + String cipherText = ""; + String algorithm = "AEAD_SM4_GCM"; + return savePlatformCert(associatedData, nonce, cipherText, algorithm, wxPayV3Bean.getPlatformCertPath()); + } catch (Exception e) { + log.error("保存国密平台证书异常", e); + return e.getMessage(); + } + } + + @RequestMapping("/get") + @ResponseBody + public String v3Get() { + // 获取平台证书列表 + try { + IJPayHttpResponse response = WxPayApi.v3( + RequestMethodEnum.GET, + WxDomainEnum.CHINA.toString(), + CertAlgorithmTypeEnum.getCertSuffixUrl(CertAlgorithmTypeEnum.SM2.getCode()), + wxPayV3Bean.getMchId(), + getSerialNumber(), + null, + wxPayV3Bean.getKeyPath(), + "", + AuthTypeEnum.RSA.getCode() + ); + Map> headers = response.getHeaders(); + log.info("请求头: {}", headers); + String timestamp = response.getHeader("Wechatpay-Timestamp"); + String nonceStr = response.getHeader("Wechatpay-Nonce"); + String serialNumber = response.getHeader("Wechatpay-Serial"); + String signature = response.getHeader("Wechatpay-Signature"); + + String body = response.getBody(); + int status = response.getStatus(); + + log.info("serialNumber: {}", serialNumber); + log.info("status: {}", status); + log.info("body: {}", body); + int isOk = 200; + if (status == isOk) { + JSONObject jsonObject = JSONUtil.parseObj(body); + JSONArray dataArray = jsonObject.getJSONArray("data"); + // 默认认为只有一个平台证书 + JSONObject encryptObject = dataArray.getJSONObject(0); + JSONObject encryptCertificate = encryptObject.getJSONObject("encrypt_certificate"); + String associatedData = encryptCertificate.getStr("associated_data"); + String cipherText = encryptCertificate.getStr("ciphertext"); + String nonce = encryptCertificate.getStr("nonce"); + String algorithm = encryptCertificate.getStr("algorithm"); + String serialNo = encryptObject.getStr("serial_no"); + final String platSerialNo = savePlatformCert(associatedData, nonce, cipherText, algorithm, wxPayV3Bean.getPlatformCertPath()); + log.info("平台证书序列号: {} serialNo: {}", platSerialNo, serialNo); + // 根据证书序列号查询对应的证书来验证签名结果 + boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Bean.getPlatformCertPath()); + log.info("verifySignature:{}", verifySignature); + } + return body; + } catch (Exception e) { + log.error("获取平台证书列表异常", e); + return null; + } + } + + @RequestMapping("/nativePay") + @ResponseBody + public String nativePay() { + try { + String timeExpire = DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 3); + UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel() + .setAppid(wxPayV3Bean.getAppId()) + .setMchid(wxPayV3Bean.getMchId()) + .setDescription("IJPay 让支付触手可及") + .setOut_trade_no(PayKit.generateStr()) + .setTime_expire(timeExpire) + .setAttach("微信系开发脚手架 https://gitee.com/javen205/TNWX") + .setNotify_url(wxPayV3Bean.getDomain().concat("/v3/payNotify")) + .setAmount(new Amount().setTotal(1)); + + log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel)); + IJPayHttpResponse response = WxPayApi.v3( + RequestMethodEnum.POST, + WxDomainEnum.CHINA.toString(), + BasePayApiEnum.NATIVE_PAY.toString(), + wxPayV3Bean.getMchId(), + getSerialNumber(), + null, + wxPayV3Bean.getKeyPath(), + JSONUtil.toJsonStr(unifiedOrderModel), + AuthTypeEnum.RSA.getCode() + ); + log.info("统一下单响应 {}", response); + // 根据证书序列号查询对应的证书来验证签名结果 + boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Bean.getPlatformCertPath()); + log.info("verifySignature: {}", verifySignature); + return response.getBody(); + } catch (Exception e) { + log.error("系统异常", e); + return e.getMessage(); + } + } + + @RequestMapping("/appPay") + @ResponseBody + public String appPay() { + try { + String timeExpire = DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 3); + UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel() + .setAppid(wxPayV3Bean.getAppId()) + .setMchid(wxPayV3Bean.getMchId()) + .setDescription("IJPay 让支付触手可及") + .setOut_trade_no(PayKit.generateStr()) + .setTime_expire(timeExpire) + .setAttach("微信系开发脚手架 https://gitee.com/javen205/TNWX") + .setNotify_url(wxPayV3Bean.getDomain().concat("/v3/payNotify")) + .setAmount(new Amount().setTotal(1)); + + log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel)); + IJPayHttpResponse response = WxPayApi.v3( + RequestMethodEnum.POST, + WxDomainEnum.CHINA.toString(), + BasePayApiEnum.APP_PAY.toString(), + wxPayV3Bean.getMchId(), + getSerialNumber(), + null, + wxPayV3Bean.getKeyPath(), + JSONUtil.toJsonStr(unifiedOrderModel), + AuthTypeEnum.RSA.getCode() + ); + log.info("统一下单响应 {}", response); + // 根据证书序列号查询对应的证书来验证签名结果 + boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Bean.getPlatformCertPath()); + log.info("verifySignature: {}", verifySignature); + if (response.getStatus() == OK && verifySignature) { + String body = response.getBody(); + JSONObject jsonObject = JSONUtil.parseObj(body); + String prepayId = jsonObject.getStr("prepay_id"); + Map map = WxPayKit.appCreateSign(wxPayV3Bean.getAppId(), wxPayV3Bean.getMchId(), prepayId, wxPayV3Bean.getKeyPath()); + log.info("唤起支付参数:{}", map); + return JSONUtil.toJsonStr(map); + } + return JSONUtil.toJsonStr(response); + } catch (Exception e) { + log.error("系统异常", e); + return e.getMessage(); + } + } + + + @RequestMapping("/query") + @ResponseBody + public String query(@RequestParam String outTradeNo) { + try { + Map params = new HashMap<>(16); + params.put("mchid", wxPayV3Bean.getMchId()); + + log.info("统一下单参数 {}", JSONUtil.toJsonStr(params)); + IJPayHttpResponse response = WxPayApi.v3( + RequestMethodEnum.GET, + WxDomainEnum.CHINA.toString(), + String.format(BasePayApiEnum.ORDER_QUERY_BY_OUT_TRADE_NO.toString(), outTradeNo), + wxPayV3Bean.getMchId(), + getSerialNumber(), + null, + wxPayV3Bean.getKeyPath(), + params, + AuthTypeEnum.RSA.getCode() + ); + log.info("查询响应 {}", response); + if (response.getStatus() == OK) { + // 根据证书序列号查询对应的证书来验证签名结果 + boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Bean.getPlatformCertPath()); + log.info("verifySignature: {}", verifySignature); + return response.getBody(); + } + return JSONUtil.toJsonStr(response); + } catch (Exception e) { + log.error("系统异常", e); + return e.getMessage(); + } + } + + + @RequestMapping("/jsApiPay") + @ResponseBody + public String jsApiPay(@RequestParam(value = "openId", required = false, defaultValue = "o-_-itxuXeGW3O1cxJ7FXNmq8Wf8") String openId) { + try { + String timeExpire = DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 3); + UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel() + .setAppid(wxPayV3Bean.getAppId()) + .setMchid(wxPayV3Bean.getMchId()) + .setDescription("IJPay 让支付触手可及") + .setOut_trade_no(PayKit.generateStr()) + .setTime_expire(timeExpire) + .setAttach("微信系开发脚手架 https://gitee.com/javen205/TNWX") + .setNotify_url(wxPayV3Bean.getDomain().concat("/v3/payNotify")) + .setAmount(new Amount().setTotal(1)) + .setPayer(new Payer().setOpenid(openId)); + + log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel)); + IJPayHttpResponse response = WxPayApi.v3( + RequestMethodEnum.POST, + WxDomainEnum.CHINA.toString(), + BasePayApiEnum.JS_API_PAY.toString(), + wxPayV3Bean.getMchId(), + getSerialNumber(), + null, + wxPayV3Bean.getKeyPath(), + JSONUtil.toJsonStr(unifiedOrderModel) + ); + log.info("统一下单响应 {}", response); + // 根据证书序列号查询对应的证书来验证签名结果 + boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Bean.getPlatformCertPath()); + log.info("verifySignature: {}", verifySignature); + if (response.getStatus() == OK && verifySignature) { + String body = response.getBody(); + JSONObject jsonObject = JSONUtil.parseObj(body); + String prepayId = jsonObject.getStr("prepay_id"); + Map map = WxPayKit.jsApiCreateSign(wxPayV3Bean.getAppId(), prepayId, wxPayV3Bean.getKeyPath()); + log.info("唤起支付参数:{}", map); + return JSONUtil.toJsonStr(map); + } + return JSONUtil.toJsonStr(response); + } catch (Exception e) { + log.error("系统异常", e); + return e.getMessage(); + } + } + + @RequestMapping("/wapPay") + @ResponseBody + public String wapPay() { + try { + String timeExpire = DateTimeZoneUtil.dateToTimeZone(System.currentTimeMillis() + 1000 * 60 * 3); + UnifiedOrderModel unifiedOrderModel = new UnifiedOrderModel() + .setAppid(wxPayV3Bean.getAppId()) + .setMchid(wxPayV3Bean.getMchId()) + .setDescription("IJPay 让支付触手可及") + .setOut_trade_no(PayKit.generateStr()) + .setTime_expire(timeExpire) + .setAttach("微信系开发脚手架 https://gitee.com/javen205/TNWX") + .setNotify_url(wxPayV3Bean.getDomain().concat("/v3/payNotify")) + .setAmount(new Amount().setTotal(1)) + .setScene_info( + new SceneInfo() + .setPayer_client_ip(""). + setH5_info(new H5Info() + .setType("Wap"))); + + log.info("统一下单参数 {}", JSONUtil.toJsonStr(unifiedOrderModel)); + IJPayHttpResponse response = WxPayApi.v3( + RequestMethodEnum.POST, + WxDomainEnum.CHINA.toString(), + BasePayApiEnum.H5_PAY.toString(), + wxPayV3Bean.getMchId(), + getSerialNumber(), + null, + wxPayV3Bean.getKeyPath(), + JSONUtil.toJsonStr(unifiedOrderModel) + ); + log.info("统一下单响应 {}", response); + // 根据证书序列号查询对应的证书来验证签名结果 + boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Bean.getPlatformCertPath()); + log.info("verifySignature: {}", verifySignature); + if (response.getStatus() == OK && verifySignature) { + String body = response.getBody(); + return JSONUtil.toJsonStr(body); + } + return JSONUtil.toJsonStr(response); + } catch (Exception e) { + log.error("系统异常", e); + return e.getMessage(); + } + } + + @RequestMapping("/batchTransfer") + @ResponseBody + public String batchTransfer(@RequestParam(value = "openId", required = false, defaultValue = "o-_-itxuXeGW3O1cxJ7FXNmq8Wf8") String openId) { + try { + BatchTransferModel batchTransferModel = new BatchTransferModel() + .setAppid(wxPayV3Bean.getAppId()) + .setOut_batch_no(PayKit.generateStr()) + .setBatch_name("IJPay 测试微信转账到零钱") + .setBatch_remark("IJPay 测试微信转账到零钱") + .setTotal_amount(1) + .setTotal_num(1) + .setTransfer_detail_list(Collections.singletonList( + new TransferDetailInput() + .setOut_detail_no(PayKit.generateStr()) + .setTransfer_amount(1) + .setTransfer_remark("IJPay 测试微信转账到零钱") + .setOpenid(openId))); + + log.info("发起商家转账请求参数 {}", JSONUtil.toJsonStr(batchTransferModel)); + IJPayHttpResponse response = WxPayApi.v3( + RequestMethodEnum.POST, + WxDomainEnum.CHINA.toString(), + TransferApiEnum.TRANSFER_BATCHES.toString(), + wxPayV3Bean.getMchId(), + getSerialNumber(), + null, + wxPayV3Bean.getKeyPath(), + JSONUtil.toJsonStr(batchTransferModel) + ); + log.info("发起商家转账响应 {}", response); + // 根据证书序列号查询对应的证书来验证签名结果 + boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Bean.getPlatformCertPath()); + log.info("verifySignature: {}", verifySignature); + if (response.getStatus() == OK && verifySignature) { + return response.getBody(); + } + return JSONUtil.toJsonStr(response); + } catch (Exception e) { + log.error("系统异常", e); + return e.getMessage(); + } + } + + + @RequestMapping("/put") + @ResponseBody + public String put() { + try { + Map params = new HashMap<>(); + params.put("url", "https://gitee.com/javen205/IJPay"); + + IJPayHttpResponse response = WxPayApi.v3( + RequestMethodEnum.PUT, + WxDomainEnum.CHINA.toString(), + ComplaintsApiEnum.COMPLAINTS_NOTIFICATION.toString(), + wxPayV3Bean.getMchId(), + getSerialNumber(), + null, + wxPayV3Bean.getKeyPath(), + JSONUtil.toJsonStr(params) + ); + // 根据证书序列号查询对应的证书来验证签名结果 + boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Bean.getPlatformCertPath()); + log.info("verifySignature: {}", verifySignature); + log.info("响应 {}", response); + return response.getBody(); + } catch (Exception e) { + log.error("系统异常", e); + return e.getMessage(); + } + } + + + @RequestMapping("/getParams") + @ResponseBody + public String payScoreServiceOrder() { + try { + Map params = new HashMap<>(); + params.put("service_id", "500001"); + params.put("appid", "wxd678efh567hg6787"); + params.put("out_order_no", "1234323JKHDFE1243252"); + + IJPayHttpResponse result = WxPayApi.v3( + RequestMethodEnum.GET, + WxDomainEnum.CHINA.toString(), + PayScoreApiEnum.PAY_SCORE_SERVICE_ORDER.toString(), + wxPayV3Bean.getMchId(), + getSerialNumber(), + null, + wxPayV3Bean.getKeyPath(), + params + ); + System.out.println(result); + return JSONUtil.toJsonStr(result); + } catch (Exception e) { + log.error("系统异常", e); + return e.getMessage(); + } + } + + @RequestMapping("/delete") + @ResponseBody + public String v3Delete() { + // 创建/查询/更新/删除投诉通知回调 + try { + HashMap hashMap = new HashMap<>(12); + hashMap.put("url", "https://qq.com"); + IJPayHttpResponse result = WxPayApi.v3( + RequestMethodEnum.POST, + WxDomainEnum.CHINA.toString(), + ComplaintsApiEnum.COMPLAINTS_NOTIFICATION.toString(), + wxPayV3Bean.getMchId(), + getSerialNumber(), + null, + wxPayV3Bean.getKeyPath(), + JSONUtil.toJsonStr(hashMap) + ); + System.out.println(result); + + result = WxPayApi.v3( + RequestMethodEnum.DELETE, + WxDomainEnum.CHINA.toString(), + ComplaintsApiEnum.COMPLAINTS_NOTIFICATION.toString(), + wxPayV3Bean.getMchId(), + getSerialNumber(), + null, + wxPayV3Bean.getKeyPath(), + "" + ); + // 根据证书序列号查询对应的证书来验证签名结果 + boolean verifySignature = WxPayKit.verifySignature(result, wxPayV3Bean.getPlatformCertPath()); + System.out.println("verifySignature:" + verifySignature); + // 如果返回的为 204 表示删除成功 + System.out.println(result); + return JSONUtil.toJsonStr(result); + } catch (Exception e) { + log.error("系统异常", e); + return e.getMessage(); + } + } + + @RequestMapping("/upload") + @ResponseBody + public String v3Upload() { + // v3 接口上传文件 + try { + String filePath = "/Users/Javen/Documents/pic/cat.png"; + + File file = FileUtil.newFile(filePath); + String sha256 = SecureUtil.sha256(file); + + HashMap map = new HashMap<>(); + map.put("filename", file.getName()); + map.put("sha256", sha256); + String body = JSONUtil.toJsonStr(map); + + System.out.println(body); + + IJPayHttpResponse result = WxPayApi.v3( + WxDomainEnum.CHINA.toString(), + OtherApiEnum.MERCHANT_UPLOAD_MEDIA.toString(), + wxPayV3Bean.getMchId(), + getSerialNumber(), + null, + wxPayV3Bean.getKeyPath(), + body, + file + ); + // 根据证书序列号查询对应的证书来验证签名结果 + boolean verifySignature = WxPayKit.verifySignature(result, wxPayV3Bean.getPlatformCertPath()); + System.out.println("verifySignature:" + verifySignature); + System.out.println(result); + return JSONUtil.toJsonStr(result); + } catch (Exception e) { + log.error("系统异常", e); + return e.getMessage(); + } + } + + @RequestMapping("/post") + @ResponseBody + public String payGiftActivity() { + // 支付有礼-终止活动 + try { + String urlSuffix = String.format(PayGiftActivityApiEnum.PAY_GIFT_ACTIVITY_TERMINATE.toString(), "10028001"); + System.out.println(urlSuffix); + IJPayHttpResponse result = WxPayApi.v3( + RequestMethodEnum.POST, + WxDomainEnum.CHINA.toString(), + urlSuffix, + wxPayV3Bean.getMchId(), + getSerialNumber(), + null, + wxPayV3Bean.getKeyPath(), + "" + ); + System.out.println(result); + return JSONUtil.toJsonStr(result); + } catch (Exception e) { + log.error("系统异常", e); + return e.getMessage(); + } + } + + @RequestMapping("/sensitive") + @ResponseBody + public String sensitive() { + // 带有敏感信息接口 + try { + String body = "处理请求参数"; + + IJPayHttpResponse result = WxPayApi.v3( + RequestMethodEnum.POST, + WxDomainEnum.CHINA.toString(), + Apply4SubApiEnum.APPLY_4_SUB.toString(), + wxPayV3Bean.getMchId(), + getSerialNumber(), + getPlatSerialNumber(), + wxPayV3Bean.getKeyPath(), + body + ); + System.out.println(result); + return JSONUtil.toJsonStr(result); + } catch (Exception e) { + log.error("系统异常", e); + return e.getMessage(); + } + } + + public static String sm2Encrypt(String plainText, SM2 sm2) { + byte[] dateBytes = plainText.getBytes(); + // 这里需要手动设置,sm2 对象的默认值与我们期望的不一致 + sm2.setMode(SM2Engine.Mode.C1C2C3); + sm2.setEncoding(new PlainDSAEncoding()); + // 加密 + byte[] encrypt = sm2.encrypt(dateBytes); + return HexUtil.encodeHexStr(encrypt); + } + + public static String sm2Decrypt(String cipherText, SM2 sm2) { + // 解密 + byte[] decrypt = sm2.decrypt(HexUtil.decodeHex(cipherText)); + return new String(decrypt); + } + + @RequestMapping("/cipher") + @ResponseBody + public String cipher(@RequestParam(required = false) String authType) { + try { + String plainText = "IJPay"; + String privateKeyPath = wxPayV3Bean.getKeyPath(); + String publicKeyPath = wxPayV3Bean.getPublicKeyPath(); + if (StrUtil.equals(authType, AuthTypeEnum.SM2.getCode())) { + String privateKeyByContent = PayKit.getPrivateKeyByContent(PayKit.getCertFileContent(privateKeyPath)); + String publicKeyByContent = PayKit.getPublicKeyByContent(PayKit.getCertFileContent(publicKeyPath)); + + PrivateKey privateKey = PayKit.getPrivateKey(privateKeyPath, AuthTypeEnum.SM2.getCode()); + PublicKey publicKey = PayKit.getSmPublicKey(publicKeyByContent); + + // 创建sm2 对象 + SM2 sm2 = SmUtil.sm2(privateKey, publicKey); + // SM2 sm2 = SmUtil.sm2(privateKeyByContent, publicKeyByContent); + String encrypt = sm2Encrypt(plainText, sm2); + log.info("加密: {}", encrypt); + log.info("解密: {}", sm2Decrypt(encrypt, sm2)); + } else { + // 敏感信息加密 + X509Certificate certificate = PayKit.getCertificate(FileUtil.getInputStream(wxPayV3Bean.getPlatformCertPath())); + String encrypt = PayKit.rsaEncryptOAEP(plainText, certificate); + log.info("明文:{} 加密后密文:{}", plainText, encrypt); + // 敏感信息解密 + String encryptStr = ""; + PrivateKey privateKey = PayKit.getPrivateKey(wxPayV3Bean.getKeyPath(), AuthTypeEnum.RSA.getCode()); + String decrypt = PayKit.rsaDecryptOAEP(encryptStr, privateKey); + log.info("解密后明文:{}", decrypt); + } + } catch (Exception e) { + log.error("系统异常", e); + return e.getMessage(); + } + return null; + } + + /** + * 申请交易账单 + * + * @param billDate 2020-06-14 当天账单后一天出,不然会出现「账单日期格式不正确」错误 + * @return 交易账单下载地址 + */ + @RequestMapping("/tradeBill") + @ResponseBody + public String tradeBill(@RequestParam(value = "billDate", required = false) String billDate) { + try { + if (StrUtil.isEmpty(billDate)) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(new Date()); + calendar.add(Calendar.DATE, -1); + billDate = DateUtil.format(calendar.getTime(), "YYYY-MM-dd"); + } + Map params = new HashMap<>(12); + params.put("bill_date", billDate); + params.put("bill_type", "ALL"); + params.put("tar_type", "GZIP"); + + IJPayHttpResponse result = WxPayApi.v3( + RequestMethodEnum.GET, + WxDomainEnum.CHINA.toString(), + BasePayApiEnum.TRADE_BILL.toString(), + wxPayV3Bean.getMchId(), + getSerialNumber(), + null, + wxPayV3Bean.getKeyPath(), + params + ); + // 根据证书序列号查询对应的证书来验证签名结果 + boolean verifySignature = WxPayKit.verifySignature(result, wxPayV3Bean.getPlatformCertPath()); + log.info("verifySignature: {}", verifySignature); + log.info("result:{}", result); + return JSONUtil.toJsonStr(result); + } catch (Exception e) { + log.error("系统异常", e); + return e.getMessage(); + } + } + + /** + * 申请资金账单 + * + * @param billDate 2020-06-14 当天账单后一天出,不然会出现「账单日期格式不正确」错误 + * @return 资金账单下载地址 + */ + @RequestMapping("/fundFlowBill") + @ResponseBody + public String fundFlowBill(@RequestParam(value = "billDate", required = false) String billDate) { + try { + if (StrUtil.isEmpty(billDate)) { + Calendar calendar = Calendar.getInstance(); + calendar.setTime(new Date()); + calendar.add(Calendar.DATE, -1); + billDate = DateUtil.format(calendar.getTime(), "YYYY-MM-dd"); + } + Map params = new HashMap<>(12); + params.put("bill_date", billDate); + params.put("account_type", "BASIC"); + + IJPayHttpResponse result = WxPayApi.v3( + RequestMethodEnum.GET, + WxDomainEnum.CHINA.toString(), + BasePayApiEnum.FUND_FLOW_BILL.toString(), + wxPayV3Bean.getMchId(), + getSerialNumber(), + null, + wxPayV3Bean.getKeyPath(), + params + ); + // 根据证书序列号查询对应的证书来验证签名结果 + boolean verifySignature = WxPayKit.verifySignature(result, wxPayV3Bean.getPlatformCertPath()); + log.info("verifySignature: {}", verifySignature); + log.info("result:{}", result); + return JSONUtil.toJsonStr(result); + } catch (Exception e) { + log.error("系统异常", e); + return e.getMessage(); + } + } + + @RequestMapping("/billDownload") + @ResponseBody + public String billDownload(@RequestParam(value = "token") String token, + @RequestParam(value = "tarType", required = false) String tarType) { + try { + + Map params = new HashMap<>(12); + params.put("token", token); + if (StrUtil.isNotEmpty(tarType)) { + params.put("tartype", tarType); + } + + IJPayHttpResponse result = WxPayApi.v3( + RequestMethodEnum.GET, + WxDomainEnum.CHINA.toString(), + BasePayApiEnum.BILL_DOWNLOAD.toString(), + wxPayV3Bean.getMchId(), + getSerialNumber(), + null, + wxPayV3Bean.getKeyPath(), + params + ); + log.info("result:{}", result); + return JSONUtil.toJsonStr(result); + } catch (Exception e) { + log.error("系统异常", e); + return e.getMessage(); + } + } + + @RequestMapping("/refund") + @ResponseBody + public String refund(@RequestParam(required = false) String transactionId, + @RequestParam(required = false) String outTradeNo) { + try { + String outRefundNo = PayKit.generateStr(); + log.info("商户退款单号: {}", outRefundNo); + + List list = new ArrayList<>(); + RefundGoodsDetail refundGoodsDetail = new RefundGoodsDetail() + .setMerchant_goods_id("123") + .setGoods_name("IJPay 测试") + .setUnit_price(1) + .setRefund_amount(1) + .setRefund_quantity(1); + list.add(refundGoodsDetail); + + RefundModel refundModel = new RefundModel() + .setOut_refund_no(outRefundNo) + .setReason("IJPay 测试退款") + .setNotify_url(wxPayV3Bean.getDomain().concat("/v3/refundNotify")) + .setAmount(new RefundAmount().setRefund(1).setTotal(1).setCurrency("CNY")) + .setGoods_detail(list); + + if (StrUtil.isNotEmpty(transactionId)) { + refundModel.setTransaction_id(transactionId); + } + if (StrUtil.isNotEmpty(outTradeNo)) { + refundModel.setOut_trade_no(outTradeNo); + } + log.info("退款参数 {}", JSONUtil.toJsonStr(refundModel)); + IJPayHttpResponse response = WxPayApi.v3( + RequestMethodEnum.POST, + WxDomainEnum.CHINA.toString(), + BasePayApiEnum.REFUND.toString(), + wxPayV3Bean.getMchId(), + getSerialNumber(), + null, + wxPayV3Bean.getKeyPath(), + JSONUtil.toJsonStr(refundModel) + ); + // 根据证书序列号查询对应的证书来验证签名结果 + boolean verifySignature = WxPayKit.verifySignature(response, wxPayV3Bean.getPlatformCertPath()); + log.info("verifySignature: {}", verifySignature); + log.info("退款响应 {}", response); + + if (verifySignature) { + return response.getBody(); + } + } catch (Exception e) { + log.error("系统异常", e); + return e.getMessage(); + } + return null; + } + + @RequestMapping(value = "/payNotify", method = {org.springframework.web.bind.annotation.RequestMethod.POST, org.springframework.web.bind.annotation.RequestMethod.GET}) + @ResponseBody + public void payNotify(HttpServletRequest request, HttpServletResponse response) { + Map map = new HashMap<>(12); + try { + String timestamp = request.getHeader("Wechatpay-Timestamp"); + String nonce = request.getHeader("Wechatpay-Nonce"); + String serialNo = request.getHeader("Wechatpay-Serial"); + String signature = request.getHeader("Wechatpay-Signature"); + + log.info("timestamp:{} nonce:{} serialNo:{} signature:{}", timestamp, nonce, serialNo, signature); + String result = HttpKit.readData(request); + log.info("支付通知密文 {}", result); + + // 需要通过证书序列号查找对应的证书,verifyNotify 中有验证证书的序列号 + String plainText = WxPayKit.verifyNotify(serialNo, result, signature, nonce, timestamp, + wxPayV3Bean.getApiKey3(), wxPayV3Bean.getPlatformCertPath()); + + log.info("支付通知明文 {}", plainText); + + if (StrUtil.isNotEmpty(plainText)) { + response.setStatus(200); + map.put("code", "SUCCESS"); + map.put("message", "SUCCESS"); + } else { + response.setStatus(500); + map.put("code", "ERROR"); + map.put("message", "签名错误"); + } + response.setHeader("Content-type", ContentType.JSON.toString()); + response.getOutputStream().write(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8)); + response.flushBuffer(); + } catch (Exception e) { + log.error("系统异常", e); + } + } +} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/config/UnionPayConfig.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/config/UnionPayConfig.java deleted file mode 100644 index 2671f0d..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/config/UnionPayConfig.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.wfc.payment.unionpay.config; - -import lombok.Data; - -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.context.annotation.Configuration; - -@Data -@Configuration -@ConfigurationProperties(prefix = "unionpay") -public class UnionPayConfig { - - private String acpRootCert; - private String acpMiddleCert; - private String keyPrivateCert; - private String keyPrivateCertPwd; - private Boolean certSign; - - // Getters and setters - public String getAcpRootCert() { - return acpRootCert; - } - - public void setAcpRootCert(String acpRootCert) { - this.acpRootCert = acpRootCert; - } - - public String getAcpMiddleCert() { - return acpMiddleCert; - } - - public void setAcpMiddleCert(String acpMiddleCert) { - this.acpMiddleCert = acpMiddleCert; - } - - public String getKeyPrivateCert() { - return keyPrivateCert; - } - - public void setKeyPrivateCert(String keyPrivateCert) { - this.keyPrivateCert = keyPrivateCert; - } - - public String getKeyPrivateCertPwd() { - return keyPrivateCertPwd; - } - - public void setKeyPrivateCertPwd(String keyPrivateCertPwd) { - this.keyPrivateCertPwd = keyPrivateCertPwd; - } - public Boolean getCertSign() { - return certSign; - } - - public void setCertSign(Boolean certSign) { - this.certSign = certSign; - } - -} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/config/UnionPayServiceConfig.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/config/UnionPayServiceConfig.java deleted file mode 100644 index d34c275..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/config/UnionPayServiceConfig.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.wfc.payment.unionpay.config; - -import com.egzosn.pay.union.api.UnionPayConfigStorage; -import com.egzosn.pay.union.api.UnionPayService; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import com.egzosn.pay.common.util.sign.SignUtils; -import com.egzosn.pay.common.bean.CertStoreType; - -//@Configuration -public class UnionPayServiceConfig { - - private final UnionPayConfig unionPayConfig; - - public UnionPayServiceConfig(UnionPayConfig unionPayConfig) { - this.unionPayConfig = unionPayConfig; - } - - @Bean - public UnionPayService unionPayService() { - UnionPayConfigStorage unionPayConfigStorage = new UnionPayConfigStorage(); - unionPayConfigStorage.setMerId("700000000000001"); - unionPayConfigStorage.setCertSign(unionPayConfig.getCertSign()); - unionPayConfigStorage.setAcpMiddleCert(unionPayConfig.getAcpMiddleCert()); - unionPayConfigStorage.setAcpRootCert(unionPayConfig.getAcpRootCert()); - unionPayConfigStorage.setKeyPrivateCert(unionPayConfig.getKeyPrivateCert()); - unionPayConfigStorage.setKeyPrivateCertPwd(unionPayConfig.getKeyPrivateCertPwd()); - unionPayConfigStorage.setCertStoreType(CertStoreType.PATH); // 使用文件存储方式 - - unionPayConfigStorage.setReturnUrl("http://wfc-gateway:8080/payment/unionpay/payBack.json"); - unionPayConfigStorage.setNotifyUrl("http://wfc-gateway:8080/payment/unionpay/payBack.json"); - unionPayConfigStorage.setSignType(SignUtils.RSA2.name()); - unionPayConfigStorage.setPayType("UNION_PAY"); - unionPayConfigStorage.setInputCharset("UTF-8"); - unionPayConfigStorage.setTest(true); - - return new UnionPayService(unionPayConfigStorage); - } -} \ No newline at end of file diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/controller/UnionPayController.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/controller/UnionPayController.java deleted file mode 100644 index d879ec8..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/controller/UnionPayController.java +++ /dev/null @@ -1,294 +0,0 @@ - -package org.wfc.payment.unionpay.controller; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.math.BigDecimal; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import javax.annotation.PostConstruct; -import javax.imageio.ImageIO; -import javax.servlet.http.HttpServletRequest; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import org.wfc.payment.unionpay.model.QueryOrder; - -import static com.egzosn.pay.union.bean.UnionTransactionType.WEB; - -import com.egzosn.pay.common.bean.CertStoreType; -import com.egzosn.pay.common.bean.PayOrder; -import com.egzosn.pay.common.bean.RefundOrder; -import com.egzosn.pay.common.http.HttpConfigStorage; -import com.egzosn.pay.common.util.sign.SignTextUtils; -import com.egzosn.pay.common.util.sign.SignUtils; -import com.egzosn.pay.union.api.UnionPayConfigStorage; -import com.egzosn.pay.union.api.UnionPayService; -import com.egzosn.pay.union.bean.UnionRefundResult; -import com.egzosn.pay.union.bean.UnionTransactionType; -import com.egzosn.pay.common.bean.AssistOrder; -import com.egzosn.pay.web.support.HttpRequestNoticeParams; -import org.wfc.payment.unionpay.config.UnionPayConfig; - -/** - * Union pay controller - * - */ -//@RestController -@RequestMapping("unionpay") -public class UnionPayController { - - private UnionPayService unionPayService = null; - private final UnionPayConfig unionPayConfig; - - @Autowired - public UnionPayController(UnionPayService unionPayService, UnionPayConfig unionPayConfig) { - this.unionPayService = unionPayService; - this.unionPayConfig = unionPayConfig; - } - - @PostConstruct - public void init() { - // UnionPayConfigStorage unionPayConfigStorage = new UnionPayConfigStorage(); - // unionPayConfigStorage.setMerId("700000000000001"); - // //是否为证书签名 - // unionPayConfigStorage.setCertSign(true); - // //中级证书路径 - // unionPayConfigStorage.setAcpMiddleCert(unionPayConfig.getAcpMiddleCert()); - // //根证书路径 - // unionPayConfigStorage.setAcpRootCert(unionPayConfig.getAcpRootCert()); - // // 私钥证书路径 - // unionPayConfigStorage.setKeyPrivateCert(unionPayConfig.getKeyPrivateCert()); - // //私钥证书对应的密码 - // unionPayConfigStorage.setKeyPrivateCertPwd(unionPayConfig.getKeyPrivateCertPwd()); - // //设置证书对应的存储方式,这里默认为文件地址 - // unionPayConfigStorage.setCertStoreType(CertStoreType.URL); - - - // //前台通知网址 即SDKConstants.param_frontUrl - // unionPayConfigStorage.setReturnUrl("http://wfc-gateway:8080/payment/unionpay/payBack.json"); - // //后台通知地址 即SDKConstants.param_backUrl - // unionPayConfigStorage.setNotifyUrl("http://wfc-gateway:8080/payment/unionpay/payBack.json"); - // //加密方式 - // unionPayConfigStorage.setSignType(SignUtils.RSA2.name()); - // //单一支付可不填 - // unionPayConfigStorage.setPayType("UNION_PAY"); - // unionPayConfigStorage.setInputCharset("UTF-8"); - // //是否为测试账号,沙箱环境 - // unionPayConfigStorage.setTest(true); - // unionPayService = new UnionPayService(unionPayConfigStorage); - - // //请求连接池配置 - // HttpConfigStorage httpConfigStorage = new HttpConfigStorage(); - // //最大连接数 - // httpConfigStorage.setMaxTotal(20); - // //默认的每个路由的最大连接数 - // httpConfigStorage.setDefaultMaxPerRoute(10); - // unionPayService.setRequestTemplateConfigStorage(httpConfigStorage); - - } - - /** - * ---业务实现例子1--- - * 功能:生成自动跳转的Html表单 - * 业务类型(关键字):网关支付(WEB)/手机网页支付,企业网银支付(B2B), - * @param price 金额 - * @return 生成自动跳转的Html表单 - */ - @RequestMapping(value = "toPay.html", produces = "text/html;charset=UTF-8") - public String toPay( BigDecimal price) { - //网关支付(WEB)/手机网页支付 - PayOrder order = new PayOrder("title", "摘要", null == price ? BigDecimal.valueOf(0.01) : price, UUID.randomUUID().toString().replace("-", ""), - WEB); - return unionPayService.toPay(order); - } - - /** - * ---业务实现例子2--- - * 功能:获取调起控件的tn号,支付结果等 - * 业务类型:手机控件支付产品(WAP), - * @param price 金额 - * @return 支付结果 - */ - @RequestMapping(value = "toPay.json") - public Map sendHttpRequest( BigDecimal price) { - //手机控件支付产品 - PayOrder order = new PayOrder("title", "摘要", null == price ? BigDecimal.valueOf(0.01) : price, UUID.randomUUID().toString().replace("-", "") - ,UnionTransactionType.WAP); - return unionPayService.app(order); - } - - /** - * APP 获取支付预订单信息 - * - * @return 支付预订单信息 - */ - @RequestMapping("app") - public Map app() { - Map data = new HashMap<>(); - data.put("code", 0); - PayOrder order = new PayOrder("title", "摘要", BigDecimal.valueOf(0.01), SignTextUtils.randomStr()); - //App支付 - order.setTransactionType(UnionTransactionType.APP); - data.put("orderInfo", unionPayService.app(order)); - return data; - } - - /** - * 获取二维码图像 APPLY_QR_CODE - * 二维码支付 - * @param price 金额 - * @return 二维码图像 - * @throws IOException IOException - */ - @RequestMapping(value = "toQrPay.jpg", produces = "image/jpeg;charset=UTF-8") - public byte[] toWxQrPay( BigDecimal price) throws IOException { - //获取对应的支付账户操作工具(可根据账户id) - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ImageIO.write(unionPayService.genQrPay( new PayOrder("title", "摘要", null == price ? BigDecimal.valueOf(0.01) : price, System.currentTimeMillis()+"", UnionTransactionType.APPLY_QR_CODE)), "JPEG", baos); - return baos.toByteArray(); - } - - /** - * 获取二维码地址 - * 二维码支付 - * @param price 金额 - * @return 二维码图像 - * @throws IOException IOException - */ - @RequestMapping(value = "getQrPay.json") - public String getQrPay(BigDecimal price) throws IOException { - //获取对应的支付账户操作工具(可根据账户id) - return unionPayService.getQrPay( new PayOrder("订单title", "摘要", null == price ? BigDecimal.valueOf(0.01) : price, System.currentTimeMillis()+"", UnionTransactionType.APPLY_QR_CODE)); - } - - /** - * 刷卡付,pos主动扫码付款(条码付) CONSUME - * @param authCode 授权码,条码等 - * @param price 金额 - * @return 支付结果 - */ - @RequestMapping(value = "microPay") - public Map microPay(BigDecimal price, String authCode) { - //获取对应的支付账户操作工具(可根据账户id) - //条码付 - PayOrder order = new PayOrder("egan order", "egan order", null == price ? BigDecimal.valueOf(0.01) : price, SignTextUtils.randomStr(), UnionTransactionType.CONSUME); - //设置授权码,条码等 - order.setAuthCode(authCode); - //支付结果 - Map params = unionPayService.microPay(order); - //校验 - if (unionPayService.verify(params)) { - - //支付校验通过后的处理 - //......业务逻辑处理块........ - - - } - //这里开发者自行处理 - return params; - } - - /** - * 支付回调地址 方式一 - * - * 方式二,{@link #payBack(HttpServletRequest)} 是属于简化方式, 试用与简单的业务场景 - * - * @param request 请求 - * @return 是否成功 - * @see #payBack(HttpServletRequest) - * @throws IOException IOException - * @deprecated This method is deprecated and will be removed in future versions. Use {@link #payBack(HttpServletRequest)} instead. - */ - @Deprecated - @RequestMapping(value = "payBackBefore.json") - public String payBackBefore(HttpServletRequest request) throws IOException { - - //获取支付方返回的对应参数 - Map params = unionPayService.getParameter2Map(request.getParameterMap(), request.getInputStream()); - if (null == params) { - return unionPayService.getPayOutMessage("fail", "失败").toMessage(); - } - - //校验 - if (unionPayService.verify(params)) { - //这里处理业务逻辑 - //......业务逻辑处理块........ - return unionPayService.successPayOutMessage(null).toMessage(); - } - - return unionPayService.getPayOutMessage("fail", "失败").toMessage(); - } - /** - * 支付回调地址 - * - * @param request 请求 - * - * @return 是否成功 - * - * 业务处理在对应的PayMessageHandler里面处理,在哪里设置PayMessageHandler,详情查看{@link com.egzosn.pay.common.api.PayService#setPayMessageHandler(com.egzosn.pay.common.api.PayMessageHandler)} - * - * 如果未设置 {@link com.egzosn.pay.common.api.PayMessageHandler} 那么会使用默认的 {@link com.egzosn.pay.common.api.DefaultPayMessageHandler} - * @throws IOException IOException - */ - @RequestMapping(value = "payBackOld.json") - public String payBackOld(HttpServletRequest request) throws IOException { - //业务处理在对应的PayMessageHandler里面处理,在哪里设置PayMessageHandler,详情查看com.egzosn.pay.common.api.PayService.setPayMessageHandler() - return unionPayService.payBack(request.getParameterMap(), request.getInputStream()).toMessage(); - } - /** - * 支付回调地址 - * - * @param request 请求 - * @return 是否成功 - *

- * 业务处理在对应的PayMessageHandler里面处理,在哪里设置PayMessageHandler,详情查看{@link com.egzosn.pay.common.api.PayService#setPayMessageHandler(com.egzosn.pay.common.api.PayMessageHandler)} - *

- * 如果未设置 {@link com.egzosn.pay.common.api.PayMessageHandler} 那么会使用默认的 {@link com.egzosn.pay.common.api.DefaultPayMessageHandler} - * @throws IOException IOException - */ - @RequestMapping(value = "payBack.json") - public String payBack(HttpServletRequest request) { - //业务处理在对应的PayMessageHandler里面处理,在哪里设置PayMessageHandler,详情查看com.egzosn.pay.common.api.PayService.setPayMessageHandler() - return unionPayService.payBack(new HttpRequestNoticeParams(request)).toMessage(); - } - - - /** - * 查询 - * - * @param order 订单的请求体 - * @return 返回查询回来的结果集,支付方原值返回 - */ - @RequestMapping("query") - public Map query(QueryOrder order) { - return unionPayService.query(new AssistOrder(order.getTradeNo(), order.getOutTradeNo())); - } - - - /** - * 申请退款接口 - * - * @param order 订单的请求体 - * @return 返回支付方申请退款后的结果 - */ - @RequestMapping("refund") - public UnionRefundResult refund(RefundOrder order) { - return unionPayService.refund(order); - } - - - /** - * 下载对账单 - * - * @param order 订单的请求体 - * @return 返回支付方下载对账单的结果 - */ - @RequestMapping("downloadBill") - public Object downloadBill(QueryOrder order) { - return unionPayService.downloadBill(order.getBillDate(), order.getBillType()); - } -} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/model/ApyAccount.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/model/ApyAccount.java deleted file mode 100644 index 950947d..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/model/ApyAccount.java +++ /dev/null @@ -1,188 +0,0 @@ - - -package org.wfc.payment.unionpay.model; - - -/** - * 支付账户 - * - */ -//@Table(name = "apy_account") -//@Entity -public class ApyAccount { - // 支付账号id -// @Id -// @GeneratedValue -// @Column(name = "pay_id") - private Integer payId; - // 支付合作id,商户id,差不多是支付平台的账号或id -// @Column(name = "partner") - private String partner; - // 应用id -// @Column(name = "appid") - private String appId; - // 支付平台公钥(签名校验使用),sign_type只有单一key时public_key与private_key相等,比如sign_type=MD5的情况 - private String publicKey; - // 应用私钥(生成签名) -// @Column(name = "private_key") - private String privateKey; - // 异步回调地址 -// @Column(name = "notify_url") - private String notifyUrl; - // 同步回调地址 -// @Column(name = "return_url") - private String returnUrl; - // 收款账号 -// @Column(name = "seller") - private String seller; - - //请求证书地址,请使用绝对路径 -// @Column(name = "keystore_path") - private String keystorePath; - //证书对应的密码 -// @Column(name = "store_password") - private String storePassword; - - - // 签名类型 -// @Column(name = "sign_type") - private String signType; - // 编码类型 枚举值,字符编码 utf-8,gbk等等 -// @Column(name = "input_charset") - private String inputCharset; - //支付类型,aliPay:支付宝,wxPay:微信, youdianPay: 友店微信,此处开发者自定义对应com.egzosn.pay.demo.entity.PayType枚举值 -// @Enumerated(EnumType.STRING) -// @Column(name = "pay_type") - private PayType payType; - //是否为测试环境 - private boolean isTest = false; - - public Integer getPayId() { - return payId; - } - - public void setPayId(Integer payId) { - this.payId = payId; - } - - public String getPartner() { - return partner; - } - - public void setPartner(String partner) { - this.partner = partner; - } - - public String getAppId() { - return appId; - } - - public void setAppId(String appId) { - this.appId = appId; - } - - public String getPublicKey() { - return publicKey; - } - - public void setPublicKey(String publicKey) { - this.publicKey = publicKey; - } - - public String getPrivateKey() { - return privateKey; - } - - public void setPrivateKey(String privateKey) { - this.privateKey = privateKey; - } - - public String getNotifyUrl() { - return notifyUrl; - } - - public void setNotifyUrl(String notifyUrl) { - this.notifyUrl = notifyUrl; - } - - public String getReturnUrl() { - return returnUrl; - } - - public void setReturnUrl(String returnUrl) { - this.returnUrl = returnUrl; - } - - public String getSeller() { - return seller; - } - - public void setSeller(String seller) { - this.seller = seller; - } - - public String getSignType() { - return signType; - } - - public void setSignType(String signType) { - this.signType = signType; - } - - public PayType getPayType() { - return payType; - } - - public void setPayType(PayType payType) { - this.payType = payType; - } - - public String getInputCharset() { - return inputCharset; - } - - public void setInputCharset(String inputCharset) { - this.inputCharset = inputCharset; - } - - public boolean isTest() { - return isTest; - } - - public String getKeystorePath() { - return keystorePath; - } - - public void setKeystorePath(String keystorePath) { - this.keystorePath = keystorePath; - } - - public String getStorePassword() { - return storePassword; - } - - public void setStorePassword(String storePassword) { - this.storePassword = storePassword; - } - - public void setTest(boolean test) { - isTest = test; - } - - @Override - public String toString() { - return "ApyAccount{" + - "payId=" + payId + - ", partner='" + partner + '\'' + - ", appId='" + appId + '\'' + - ", publicKey='" + publicKey + '\'' + - ", privateKey='" + privateKey + '\'' + - ", notifyUrl='" + notifyUrl + '\'' + - ", returnUrl='" + returnUrl + '\'' + - ", seller='" + seller + '\'' + - ", signType='" + signType + '\'' + - ", inputCharset='" + inputCharset + '\'' + - ", payType=" + payType + - '}'; - } -} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/model/PayType.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/model/PayType.java deleted file mode 100644 index 997e95c..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/model/PayType.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.wfc.payment.unionpay.model; - -import org.wfc.payment.unionpay.service.impl.UnionPayMessageImpl; - -import com.egzosn.pay.common.api.PayService; -import com.egzosn.pay.common.bean.BasePayType; -import com.egzosn.pay.common.bean.CertStoreType; -import com.egzosn.pay.common.bean.TransactionType; -import com.egzosn.pay.union.api.UnionPayConfigStorage; -import com.egzosn.pay.union.api.UnionPayService; -import com.egzosn.pay.union.bean.UnionTransactionType; - -/** - * 支付类型 - * - */ -public enum PayType implements BasePayType { - UNION_PAY { - @Override - public PayService getPayService(ApyAccount apyAccount) { - UnionPayConfigStorage unionPayConfigStorage = new UnionPayConfigStorage(); - unionPayConfigStorage.setMerId(apyAccount.getPartner()); - unionPayConfigStorage.setCertSign(true); - - //中级证书路径 - unionPayConfigStorage.setAcpMiddleCert("D:/certs/acp_test_middle.cer"); - //根证书路径 - unionPayConfigStorage.setAcpRootCert("D:/certs/acp_test_root.cer"); - // 私钥证书路径 - unionPayConfigStorage.setKeyPrivateCert("D:/certs/acp_test_sign.pfx"); - //私钥证书对应的密码 - unionPayConfigStorage.setKeyPrivateCertPwd("000000"); - //设置证书对应的存储方式,这里默认为文件地址 - unionPayConfigStorage.setCertStoreType(CertStoreType.PATH); - - unionPayConfigStorage.setNotifyUrl(apyAccount.getNotifyUrl()); - unionPayConfigStorage.setReturnUrl(apyAccount.getReturnUrl()); - unionPayConfigStorage.setSignType(apyAccount.getSignType()); - unionPayConfigStorage.setPayType(apyAccount.getPayType().toString()); - unionPayConfigStorage.setInputCharset(apyAccount.getInputCharset()); - unionPayConfigStorage.setTest(apyAccount.isTest()); - final UnionPayService unionPayService = new UnionPayService(unionPayConfigStorage); - unionPayService.setPayMessageHandler(new UnionPayMessageImpl(apyAccount.getPayId())); - return unionPayService; - } - - @Override - public TransactionType getTransactionType(String transactionType) { - return UnionTransactionType.valueOf(transactionType); - } - - - }; - - public abstract PayService getPayService(ApyAccount apyAccount); -} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/model/QueryOrder.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/model/QueryOrder.java deleted file mode 100644 index 8720bb1..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/model/QueryOrder.java +++ /dev/null @@ -1,130 +0,0 @@ -package org.wfc.payment.unionpay.model; - -import java.math.BigDecimal; -import java.util.Date; - -/** - * 订单辅助接口 - * @author egan - * email egzosn@gmail.com - * date 2017/3/12 14:50 - */ -public class QueryOrder { - - private Integer payId; -// 支付平台订单号 - private String tradeNo; - -// 商户单号 - private String outTradeNo; -// 退款金额 - private BigDecimal refundAmount; -// 总金额 - private BigDecimal totalAmount; -// 账单时间:具体请查看对应支付平台 - private Date billDate; -// 账单时间:具体请查看对应支付平台 - private String billType; - // 支付平台订单号或者账单日期 - private Object tradeNoOrBillDate; - // 商户单号或者 账单类型 - private String outTradeNoBillType; - // 交易类型 - private String transactionType; - - public Integer getPayId() { - return payId; - } - - public void setPayId(Integer payId) { - this.payId = payId; - } - - public String getTradeNo() { - return tradeNo; - } - - public void setTradeNo(String tradeNo) { - this.tradeNo = tradeNo; - } - - public String getOutTradeNo() { - return outTradeNo; - } - - public void setOutTradeNo(String outTradeNo) { - this.outTradeNo = outTradeNo; - } - - public BigDecimal getRefundAmount() { - return refundAmount; - } - - public void setRefundAmount(BigDecimal refundAmount) { - this.refundAmount = refundAmount; - } - - public BigDecimal getTotalAmount() { - return totalAmount; - } - - public void setTotalAmount(BigDecimal totalAmount) { - this.totalAmount = totalAmount; - } - - public Date getBillDate() { - return billDate; - } - - public void setBillDate(Date billDate) { - this.billDate = billDate; - } - - public String getBillType() { - return billType; - } - - public void setBillType(String billType) { - this.billType = billType; - } - - public Object getTradeNoOrBillDate() { - return tradeNoOrBillDate; - } - - public void setTradeNoOrBillDate(Object tradeNoOrBillDate) { - this.tradeNoOrBillDate = tradeNoOrBillDate; - } - - public String getOutTradeNoBillType() { - return outTradeNoBillType; - } - - public void setOutTradeNoBillType(String outTradeNoBillType) { - this.outTradeNoBillType = outTradeNoBillType; - } - - public String getTransactionType() { - return transactionType; - } - - public void setTransactionType(String transactionType) { - this.transactionType = transactionType; - } - - @Override - public String toString() { - return "QueryOrder{" + - "payId=" + payId + - ", tradeNo='" + tradeNo + '\'' + - ", outTradeNo='" + outTradeNo + '\'' + - ", refundAmount=" + refundAmount + - ", totalAmount=" + totalAmount + - ", billDate=" + billDate + - ", billType='" + billType + '\'' + - ", tradeNoOrBillDate=" + tradeNoOrBillDate + - ", outTradeNoBillType='" + outTradeNoBillType + '\'' + - ", transactionType='" + transactionType + '\'' + - '}'; - } -} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/repository/ApyAccountRepository.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/repository/ApyAccountRepository.java deleted file mode 100644 index 8111010..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/repository/ApyAccountRepository.java +++ /dev/null @@ -1,69 +0,0 @@ - -package org.wfc.payment.unionpay.repository; - -import java.util.HashMap; -import java.util.Map; - -import org.wfc.payment.unionpay.model.ApyAccount; -import org.wfc.payment.unionpay.model.PayType; - -import com.egzosn.pay.common.util.sign.SignUtils; - -/** - * 账户 - * - * @author egan - * email egzosn@gmail.com - * date 2016/11/18 1:21 - */ -//@Repository -public class ApyAccountRepository { - - // 这里简单模拟,引入orm等框架之后可自行删除 - protected static final Map apyAccounts = new HashMap<>(); - - /** - * 这里简单初始化,引入orm等框架之后可自行删除 - */ - static { - - ApyAccount apyAccount4 = new ApyAccount(); - apyAccount4.setPayId(4); - apyAccount4.setPartner("700000000000001"); - //公钥,验签证书链格式: 中级证书路径;根证书路径 - apyAccount4.setPublicKey("D:/certs/acp_test_middle.cer;D:/certs/acp_test_root.cer"); - //私钥, 私钥证书格式: 私钥证书路径;私钥证书对应的密码 - apyAccount4.setPrivateKey("D:/certs/acp_test_sign.pfx;000000"); - apyAccount4.setNotifyUrl("http://127.0.0.1/payBack4.json"); - // 无需同步回调可不填 app填这个就可以 - apyAccount4.setReturnUrl("http://127.0.0.1/payBack4.json"); - apyAccount4.setSeller(""); - apyAccount4.setInputCharset("UTF-8"); - apyAccount4.setSignType(SignUtils.RSA2.name()); - apyAccount4.setPayType(PayType.UNION_PAY); - apyAccount4.setTest(true); - apyAccounts.put(apyAccount4.getPayId(), apyAccount4); - } - //_____________________________________________________________ - - /** - * Provides access to the apyAccounts map. - * - * @return the apyAccounts map - */ - public static Map getApyAccounts() { - return apyAccounts; - } - - - /** - * 根据id获取对应的账户信息 - * - * @param payId 账户id - * @return 账户信息 - */ - public ApyAccount findByPayId(Integer payId) { - // Retrieve the ApyAccount from the map using the payId - return apyAccounts.get(payId); - } -} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/service/ApyAccountService.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/service/ApyAccountService.java deleted file mode 100644 index 51d9780..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/service/ApyAccountService.java +++ /dev/null @@ -1,55 +0,0 @@ - -package org.wfc.payment.unionpay.service; - -import org.wfc.payment.unionpay.model.ApyAccount; -import org.wfc.payment.unionpay.repository.ApyAccountRepository; -import org.springframework.beans.factory.config.AutowireCapableBeanFactory; -import org.springframework.stereotype.Service; -import javax.annotation.Resource; -import java.util.HashMap; -import java.util.Map; - -@Service -public class ApyAccountService { - -// @Resource - private ApyAccountRepository dao; - - @Resource - private AutowireCapableBeanFactory spring; - - /** - * 缓存 - */ - private static final Map payResponses = new HashMap<>(); - - /** - * 这里简单初始化,引入orm等框架之后可自行删除 - */ - public ApyAccountService() { - dao = new ApyAccountRepository(); - } - - - /** - * 获取支付响应 - * @param id 账户id - * @return 支付响应 - */ - public PayResponse getPayResponse(Integer id) { - - PayResponse payResponse = payResponses.get(id); - if (payResponse == null) { - ApyAccount apyAccount = dao.findByPayId(id); - if (apyAccount == null) { - throw new IllegalArgumentException ("无法查询"); - } - payResponse = new PayResponse(); - spring.autowireBean(payResponse); - payResponse.init(apyAccount); - payResponses.put(id, payResponse); - // 查询 - } - return payResponse; - } -} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/service/PayResponse.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/service/PayResponse.java deleted file mode 100644 index 37ed40c..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/service/PayResponse.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.wfc.payment.unionpay.service; - -import javax.annotation.Resource; - -import org.springframework.beans.factory.config.AutowireCapableBeanFactory; -import org.wfc.payment.unionpay.model.ApyAccount; - -import com.egzosn.pay.common.api.PayConfigStorage; -import com.egzosn.pay.common.api.PayService; -import com.egzosn.pay.common.http.HttpConfigStorage; - -/** - * 支付响应对象 - * - */ -public class PayResponse { - - @Resource - private AutowireCapableBeanFactory spring; - - private PayConfigStorage storage; - - private PayService service; - - - public PayResponse() { - // This constructor is intentionally empty. Nothing special is needed here. - } - - /** - * 初始化支付配置 - * - * @param apyAccount 账户信息 - * @see ApyAccount 对应表结构详情--》 /pay-java-demo/resources/apy_account.sql - */ - public void init(ApyAccount apyAccount) { - //根据不同的账户类型 初始化支付配置 - this.service = apyAccount.getPayType().getPayService(apyAccount); - this.storage = service.getPayConfigStorage(); - - - //这里设置http请求配置 - // buildRouter(apyAccount.getPayId()); // Deprecated method call removed - } - - /** - * 获取http配置,如果配置为null则为默认配置,无代理,无证书的请求方式。 - * 此处非必需 - * - * @param apyAccount 账户信息 - * @return 请求配置 - */ - public HttpConfigStorage getHttpConfigStorage(ApyAccount apyAccount) { - HttpConfigStorage httpConfigStorage = new HttpConfigStorage(); - /* 网路代理配置 根据需求进行设置*/ - // //http代理地址 - // httpConfigStorage.setHttpProxyHost("192.168.1.69"); - // //代理端口 - // httpConfigStorage.setHttpProxyPort(3308); - // //代理用户名 - // httpConfigStorage.setHttpProxyUsername("user"); - // //代理密码 - // httpConfigStorage.setHttpProxyPassword("password"); - // 设置ssl证书路径 https证书设置 方式二 - httpConfigStorage.setKeystore(apyAccount.getKeystorePath()); - //设置ssl证书对应的密码 - httpConfigStorage.setStorePassword(apyAccount.getStorePassword()); - return httpConfigStorage; - } - - public PayConfigStorage getStorage() { - return storage; - } - - public PayService getService() { - return service; - } - -} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/service/impl/BasePayMessageImpl.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/service/impl/BasePayMessageImpl.java deleted file mode 100644 index aa4b8d7..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/service/impl/BasePayMessageImpl.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.wfc.payment.unionpay.service.impl; - -import com.egzosn.pay.common.api.PayMessageHandler; -import com.egzosn.pay.common.api.PayService; -import com.egzosn.pay.common.bean.PayMessage; - -public abstract class BasePayMessageImpl> implements PayMessageHandler { - //支付账户id - private Integer payId; - - protected BasePayMessageImpl(Integer payId) { - this.payId = payId; - } - - public Integer getPayId() { - return payId; - } -} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/service/impl/UnionPayMessageImpl.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/service/impl/UnionPayMessageImpl.java deleted file mode 100644 index 8a38123..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/unionpay/service/impl/UnionPayMessageImpl.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.wfc.payment.unionpay.service.impl; - -import com.egzosn.pay.common.bean.PayOutMessage; -import com.egzosn.pay.common.exception.PayErrorException; -import com.egzosn.pay.union.api.UnionPayService; -import com.egzosn.pay.union.bean.SDKConstants; -import com.egzosn.pay.union.bean.UnionPayMessage; - -import java.util.Map; - -public class UnionPayMessageImpl extends BasePayMessageImpl { - - public UnionPayMessageImpl(Integer payId) { - super(payId); - } - - @Override - public PayOutMessage handle(UnionPayMessage payMessage, Map context, UnionPayService payService) throws PayErrorException { - //交易状态 - if (SDKConstants.OK_RESP_CODE.equals(payMessage.getPayMessage().get(SDKConstants.param_respCode))) { - /////这里进行成功的处理 - - return payService.successPayOutMessage(payMessage); - } - - return payService.getPayOutMessage("fail", "失败"); - } -} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/utils/StringUtils.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/utils/StringUtils.java new file mode 100644 index 0000000..86fb3ec --- /dev/null +++ b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/utils/StringUtils.java @@ -0,0 +1,150 @@ +package org.wfc.payment.utils; + +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; +import java.text.MessageFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; +import java.util.Random; +import java.util.UUID; + +/** + * 字符串工具类,继承lang3字符串工具类 + * + * @author L.com + */ +public final class StringUtils extends org.apache.commons.lang3.StringUtils { + + public static String encode(String str) { + String encode = null; + try { + encode = URLEncoder.encode(str, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + return encode; + } + + /** + * 获取UUID,去掉`-`的 + * + * @return {String} + */ + public static String generateStr() { + return UUID.randomUUID().toString().replace("-", ""); + } + + + /** + * 要求外部订单号必须唯一。 + * + * @return {String} + */ + public static String getOutTradeNo() { + SimpleDateFormat format = new SimpleDateFormat("MMddHHmmss", Locale.getDefault()); + Date date = new Date(); + String key = format.format(date); + key = key + System.currentTimeMillis(); + key = key.substring(0, 15); + return key; + } + + /** + * 字符串格式化 + *

+ * use: format("my name is {0}, and i like {1}!", "L.cm", "java") + *

+ * int long use {0,number,#} + * + * @param s + * @param args + * @return {String}转换后的字符串 + */ + public static String format(String s, Object... args) { + return MessageFormat.format(s, args); + } + + /** + * 替换某个字符 + * + * @param str + * @param regex + * @param args + * @return {String} + */ + public static String replace(String str, String regex, String... args) { + int length = args.length; + for (int i = 0; i < length; i++) { + str = str.replaceFirst(regex, args[i]); + } + return str; + } + + /** + * 清理字符串,清理出某些不可见字符 + * + * @param txt + * @return {String} + */ + public static String cleanChars(String txt) { + return txt.replaceAll("[   `·•�\\f\\t\\v]", ""); + } + + /** + * 随机字符串 + */ + private static final String INT_TEMP = "0123456789"; + private static final String STR_TEMP = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + private static final String ALL_TEMP = INT_TEMP + STR_TEMP; + + private static final Random RANDOM = new Random(); + + /** + * 生成的随机数类型 + */ + public enum RandomType { + /** + * 整数 + */ + INT, + /** + * 字符串 + */ + STRING, + /** + * 所有类型 + */ + ALL + } + + /** + * 随机数生成 + * + * @param count + * @return {String} + */ + public static String random(int count, RandomType randomType) { + if (count == 0) { + return ""; + } + if (count < 0) { + throw new IllegalArgumentException("Requested random string length " + count + " is less than 0."); + } + char[] buffer = new char[count]; + for (int i = 0; i < count; i++) { + if (randomType.equals(RandomType.INT)) { + buffer[i] = INT_TEMP.charAt(RANDOM.nextInt(INT_TEMP.length())); + } else if (randomType.equals(RandomType.STRING)) { + buffer[i] = STR_TEMP.charAt(RANDOM.nextInt(STR_TEMP.length())); + } else { + buffer[i] = ALL_TEMP.charAt(RANDOM.nextInt(ALL_TEMP.length())); + } + } + return new String(buffer); + } + + public static void main(String[] args) { + System.out.println(random(32, RandomType.ALL)); + } +} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/config/WWxPayConfig.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/config/WWxPayConfig.java deleted file mode 100644 index e1f74fd..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/config/WWxPayConfig.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.wfc.payment.wxpay.config; - -import com.github.binarywang.wxpay.config.WxPayConfig; -import com.github.binarywang.wxpay.service.WxPayService; -import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; -import lombok.AllArgsConstructor; -import org.apache.commons.lang3.StringUtils; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -@Configuration -@ConditionalOnClass(WxPayService.class) -@EnableConfigurationProperties(WxPayProperties.class) -@AllArgsConstructor -public class WWxPayConfig { - private WxPayProperties properties; - - @Bean - @ConditionalOnMissingBean - public WxPayService wxService() { - WxPayConfig payConfig = new WxPayConfig(); - payConfig.setAppId(StringUtils.trimToNull(this.properties.getAppId())); - payConfig.setMchId(StringUtils.trimToNull(this.properties.getMchId())); - payConfig.setMchKey(StringUtils.trimToNull(this.properties.getMchKey())); - payConfig.setSubAppId(StringUtils.trimToNull(this.properties.getSubAppId())); - payConfig.setSubMchId(StringUtils.trimToNull(this.properties.getSubMchId())); - payConfig.setKeyPath(StringUtils.trimToNull(this.properties.getKeyPath())); - - // 可以指定是否使用沙箱环境 - payConfig.setUseSandboxEnv(this.properties.getUseSandboxEnv()); - - WxPayService wxPayService = new WxPayServiceImpl(); - wxPayService.setConfig(payConfig); - return wxPayService; - } -} \ No newline at end of file diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/config/WxPayProperties.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/config/WxPayProperties.java deleted file mode 100644 index 6a14190..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/config/WxPayProperties.java +++ /dev/null @@ -1,48 +0,0 @@ -package org.wfc.payment.wxpay.config; - -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; - -/** - * wxpay pay properties. - * - */ -@Data -@ConfigurationProperties(prefix = "wxpay") -public class WxPayProperties { - /** - * 设置微信公众号或者小程序等的appid - */ - private String appId; - - /** - * 微信支付商户号 - */ - private String mchId; - - /** - * 微信支付商户密钥 - */ - private String mchKey; - - /** - * 服务商模式下的子商户公众账号ID,普通模式请不要配置,请在配置文件中将对应项删除 - */ - private String subAppId; - - /** - * 服务商模式下的子商户号,普通模式请不要配置,最好是请在配置文件中将对应项删除 - */ - private String subMchId; - - /** - * apiclient_cert.p12文件的绝对路径,或者如果放在项目中,请以classpath:开头指定 - */ - private String keyPath; - - /** - * 可以指定是否使用沙箱环境 - */ - private Boolean useSandboxEnv; - -} \ No newline at end of file diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/controller/WxPayController.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/controller/WxPayController.java deleted file mode 100644 index 502b6fe..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/controller/WxPayController.java +++ /dev/null @@ -1,431 +0,0 @@ -package org.wfc.payment.wxpay.controller; - -import com.alipay.api.AlipayApiException; -import com.github.binarywang.wxpay.bean.coupon.*; -import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse; -import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; -import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult; -import com.github.binarywang.wxpay.bean.notify.WxScanPayNotifyResult; -import com.github.binarywang.wxpay.bean.request.*; -import com.github.binarywang.wxpay.bean.result.*; -import com.github.binarywang.wxpay.exception.WxPayException; -import com.github.binarywang.wxpay.service.WxPayService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import lombok.AllArgsConstructor; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; -import org.wfc.payment.wxpay.service.IWxPayNotifyOrderService; -import org.wfc.payment.wxpay.service.IWxPayNotifyRefundService; -import org.wfc.payment.wxpay.service.IWxPayNotifyScanpayService; - -import java.io.File; -import java.util.Date; -import java.util.Map; - -@Tag(name = "WeChat Pay") -@RestController -@RequestMapping("/wxpay") -@AllArgsConstructor -public class WxPayController { - - private final WxPayService wxService; - - // @Autowired - // public WxPayController(WxPayService wxService) { - // this.wxService = wxService; - // } - - /** - *

-     * 查询订单(详见https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2)
-     * 该接口提供所有微信支付订单的查询,商户可以通过查询订单接口主动查询订单状态,完成下一步的业务逻辑。
-     * 需要调用查询接口的情况:
-     * ◆ 当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知;
-     * ◆ 调用支付接口后,返回系统错误或未知交易状态情况;
-     * ◆ 调用被扫支付API,返回USERPAYING的状态;
-     * ◆ 调用关单或撤销接口API之前,需确认支付状态;
-     * 接口地址:https://api.mch.weixin.qq.com/pay/orderquery
-     * 
- * - * @param transactionId 微信订单号 - * @param outTradeNo 商户系统内部的订单号,当没提供transactionId时需要传这个。 - */ - @Operation(summary = "Query order") - @GetMapping("/queryOrder") - public WxPayOrderQueryResult queryOrder(@RequestParam(required = false) String transactionId, - @RequestParam(required = false) String outTradeNo) - throws WxPayException { - return this.wxService.queryOrder(transactionId, outTradeNo); - } - - @Operation(summary = "Query order") - @PostMapping("/queryOrder") - public WxPayOrderQueryResult queryOrder(@RequestBody WxPayOrderQueryRequest wxPayOrderQueryRequest) - throws WxPayException { - return this.wxService.queryOrder(wxPayOrderQueryRequest); - } - - /** - *
-     * 关闭订单
-     * 应用场景
-     * 以下情况需要调用关单接口:
-     * 1. 商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付;
-     * 2. 系统下单后,用户支付超时,系统退出不再受理,避免用户继续,请调用关单接口。
-     * 注意:订单生成后不能马上调用关单接口,最短调用时间间隔为5分钟。
-     * 接口地址:https://api.mch.weixin.qq.com/pay/closeorder
-     * 是否需要证书:   不需要。
-     * 
- * - * @param outTradeNo 商户系统内部的订单号 - */ - @Operation(summary = "Close order") - @GetMapping("/closeOrder/{outTradeNo}") - public WxPayOrderCloseResult closeOrder(@PathVariable String outTradeNo) throws WxPayException { - return this.wxService.closeOrder(outTradeNo); - } - - @Operation(summary = "Close order") - @PostMapping("/closeOrder") - public WxPayOrderCloseResult closeOrder(@RequestBody WxPayOrderCloseRequest wxPayOrderCloseRequest) - throws WxPayException { - return this.wxService.closeOrder(wxPayOrderCloseRequest); - } - - /** - * 调用统一下单接口,并组装生成支付所需参数对象. - * - * @param request 统一下单请求参数 - * @param 请使用{@link com.github.binarywang.wxpay.bean.order}包下的类 - * @return 返回 {@link com.github.binarywang.wxpay.bean.order}包下的类对象 - */ - @Operation(summary = "统一下单,并组装所需支付参数") - @PostMapping("/createOrder") - public T createOrder(@RequestBody WxPayUnifiedOrderRequest request) throws WxPayException { - return this.wxService.createOrder(request); - } - - /** - * 统一下单(详见https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1) - * 在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识" - * 接口地址:https://api.mch.weixin.qq.com/pay/unifiedorder - * - * @param request 请求对象,注意一些参数如appid、mchid等不用设置,方法内会自动从配置对象中获取到(前提是对应配置中已经设置) - */ - @Operation(summary = "原生的统一下单接口") - @PostMapping("/unifiedOrder") - public WxPayUnifiedOrderResult unifiedOrder(@RequestBody WxPayUnifiedOrderRequest request) throws WxPayException { - return this.wxService.unifiedOrder(request); - } - - /** - *
-     * 微信支付-申请退款
-     * 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
-     * 接口链接:https://api.mch.weixin.qq.com/secapi/pay/refund
-     * 
- * - * @param request 请求对象 - * @return 退款操作结果 - */ - @Operation(summary = "Refund") - @PostMapping("/refund") - public WxPayRefundResult refund(@RequestBody WxPayRefundRequest request) throws WxPayException { - return this.wxService.refund(request); - } - - /** - *
-     * 微信支付-查询退款
-     * 应用场景:
-     *  提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用零钱支付的退款20分钟内到账,
-     *  银行卡支付的退款3个工作日后重新查询退款状态。
-     * 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5
-     * 接口链接:https://api.mch.weixin.qq.com/pay/refundquery
-     * 
- * - * 以下四个参数四选一 - * - * @param transactionId 微信订单号 - * @param outTradeNo 商户订单号 - * @param outRefundNo 商户退款单号 - * @param refundId 微信退款单号 - * @return 退款信息 - */ - @Operation(summary = "退款查询") - @GetMapping("/refundQuery") - public WxPayRefundQueryResult refundQuery(@RequestParam(required = false) String transactionId, - @RequestParam(required = false) String outTradeNo, - @RequestParam(required = false) String outRefundNo, - @RequestParam(required = false) String refundId) - throws WxPayException { - return this.wxService.refundQuery(transactionId, outTradeNo, outRefundNo, refundId); - } - - @Operation(summary = "退款查询") - @PostMapping("/refundQuery") - public WxPayRefundQueryResult refundQuery(@RequestBody WxPayRefundQueryRequest wxPayRefundQueryRequest) - throws WxPayException { - return this.wxService.refundQuery(wxPayRefundQueryRequest); - } - - private final IWxPayNotifyOrderService wxPayNotifyOrderService; - private static final String MSG_SUCCESS = "success"; - private static final String MSG_FAILURE = "failure"; - - @Operation(summary = "支付回调通知处理") - @PostMapping("/notify/order") - public String parseOrderNotifyResult(@RequestBody String xmlData) throws WxPayException { - final WxPayOrderNotifyResult notifyResult = this.wxService.parseOrderNotifyResult(xmlData); - // 根据自己业务场景需要构造返回对象 - try { - Map notifyResultMap = notifyResult.toMap(); - boolean result = wxPayNotifyOrderService.handleWxPayNotifyOrder(notifyResultMap); - return result ? MSG_SUCCESS : MSG_FAILURE; - } catch (Exception e) { - e.printStackTrace(); - return MSG_FAILURE; - } - } - - private final IWxPayNotifyRefundService wxPayNotifyRefundService; - @Operation(summary = "退款回调通知处理") - @PostMapping("/notify/refund") - public String parseRefundNotifyResult(@RequestBody String xmlData) throws WxPayException { - final WxPayRefundNotifyResult notifyResult = this.wxService.parseRefundNotifyResult(xmlData); - // 根据自己业务场景需要构造返回对象 - try { - Map notifyResultMap = notifyResult.toMap(); - boolean result = wxPayNotifyRefundService.handleWxPayNotifyRefund(notifyResultMap); - return result ? MSG_SUCCESS : MSG_FAILURE; - } catch (Exception e) { - e.printStackTrace(); - return MSG_FAILURE; - } - } - - private final IWxPayNotifyScanpayService wxPayNotifyScanpayService; - @Operation(summary = "扫码支付回调通知处理") - @PostMapping("/notify/scanpay") - public String parseScanPayNotifyResult(String xmlData) throws WxPayException { - final WxScanPayNotifyResult notifyResult = this.wxService.parseScanPayNotifyResult(xmlData); - // 根据自己业务场景需要构造返回对象 - try { - Map notifyResultMap = notifyResult.toMap(); - boolean result = wxPayNotifyScanpayService.handleWxPayNotifyScanpay(notifyResultMap); - return result ? MSG_SUCCESS : MSG_FAILURE; - } catch (Exception e) { - e.printStackTrace(); - return MSG_FAILURE; - } - } - - /** - * 发送微信红包给个人用户 - * - *
-     * 文档详见:
-     * 发送普通红包 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_4&index=3
-     *  接口地址:https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack
-     * 发送裂变红包 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_5&index=4
-     *  接口地址:https://api.mch.weixin.qq.com/mmpaymkttransfers/sendgroupredpack
-     * 
- * - * @param request 请求对象 - */ - @Operation(summary = "发送红包") - @PostMapping("/sendRedpack") - public WxPaySendRedpackResult sendRedpack(@RequestBody WxPaySendRedpackRequest request) throws WxPayException { - return this.wxService.getRedpackService().sendRedpack(request); - } - - /** - *
-     *   查询红包记录
-     *   用于商户对已发放的红包进行查询红包的具体信息,可支持普通红包和裂变包。
-     *   请求Url	https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo
-     *   是否需要证书	是(证书及使用说明详见商户证书)
-     *   请求方式	POST
-     * 
- * - * @param mchBillNo 商户发放红包的商户订单号,比如10000098201411111234567890 - */ - @Operation(summary = "查询红包") - @GetMapping("/queryRedpack/{mchBillNo}") - public WxPayRedpackQueryResult queryRedpack(@PathVariable String mchBillNo) throws WxPayException { - return this.wxService.getRedpackService().queryRedpack(mchBillNo); - } - - /** - *
-     * 扫码支付模式一生成二维码的方法
-     * 二维码中的内容为链接,形式为:
-     * weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&product_id=XXXXXX&time_stamp=XXXXXX&nonce_str=XXXXX
-     * 其中XXXXX为商户需要填写的内容,商户将该链接生成二维码,如需要打印发布二维码,需要采用此格式。商户可调用第三方库生成二维码图片。
-     * 文档详见: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4
-     * 
- * - * @param productId 产品Id - * @param logoFile 商户logo图片的文件对象,可以为空 - * @param sideLength 要生成的二维码的边长,如果为空,则取默认值400 - * @return 生成的二维码的字节数组 - */ - public byte[] createScanPayQrcodeMode1(String productId, File logoFile, Integer sideLength) throws Exception { - return this.wxService.createScanPayQrcodeMode1(productId, logoFile, sideLength); - } - - /** - *
-     * 扫码支付模式一生成二维码的方法
-     * 二维码中的内容为链接,形式为:
-     * weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&product_id=XXXXXX&time_stamp=XXXXXX&nonce_str=XXXXX
-     * 其中XXXXX为商户需要填写的内容,商户将该链接生成二维码,如需要打印发布二维码,需要采用此格式。商户可调用第三方库生成二维码图片。
-     * 文档详见: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4
-     * 
- * - * @param productId 产品Id - * @return 生成的二维码URL连接 - */ - public String createScanPayQrcodeMode1(String productId) { - return this.wxService.createScanPayQrcodeMode1(productId); - } - - /** - *
-     * 扫码支付模式二生成二维码的方法
-     * 对应链接格式:weixin://wxpay/bizpayurl?sr=XXXXX。请商户调用第三方库将code_url生成二维码图片。
-     * 该模式链接较短,生成的二维码打印到结账小票上的识别率较高。
-     * 文档详见: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5
-     * 
- * - * @param codeUrl 微信返回的交易会话的二维码链接 - * @param logoFile 商户logo图片的文件对象,可以为空 - * @param sideLength 要生成的二维码的边长,如果为空,则取默认值400 - * @return 生成的二维码的字节数组 - */ - public byte[] createScanPayQrcodeMode2(String codeUrl, File logoFile, Integer sideLength) throws Exception { - return this.wxService.createScanPayQrcodeMode2(codeUrl, logoFile, sideLength); - } - - /** - *
-     * 交易保障
-     * 应用场景:
-     *  商户在调用微信支付提供的相关接口时,会得到微信支付返回的相关信息以及获得整个接口的响应时间。
-     *  为提高整体的服务水平,协助商户一起提高服务质量,微信支付提供了相关接口调用耗时和返回信息的主动上报接口,
-     *  微信支付可以根据商户侧上报的数据进一步优化网络部署,完善服务监控,和商户更好的协作为用户提供更好的业务体验。
-     * 接口地址: https://api.mch.weixin.qq.com/payitil/report
-     * 是否需要证书:不需要
-     * 
- */ - @Operation(summary = "提交交易保障数据") - @PostMapping("/report") - public void report(@RequestBody WxPayReportRequest request) throws WxPayException { - this.wxService.report(request); - } - - /** - *
-     * 下载对账单
-     * 商户可以通过该接口下载历史交易清单。比如掉单、系统错误等导致商户侧和微信侧数据不一致,通过对账单核对后可校正支付状态。
-     * 注意:
-     * 1、微信侧未成功下单的交易不会出现在对账单中。支付成功后撤销的交易会出现在对账单中,跟原支付单订单号一致,bill_type为REVOKED;
-     * 2、微信在次日9点启动生成前一天的对账单,建议商户10点后再获取;
-     * 3、对账单中涉及金额的字段单位为“元”。
-     * 4、对账单接口只能下载三个月以内的账单。
-     * 接口链接:https://api.mch.weixin.qq.com/pay/downloadbill
-     * 详情请见: 下载对账单
-     * 
- * - * @param billDate 对账单日期 bill_date 下载对账单的日期,格式:20140603 - * @param billType 账单类型 bill_type - * ALL,返回当日所有订单信息,默认值,SUCCESS,返回当日成功支付的订单,REFUND,返回当日退款订单 - * @param tarType 压缩账单 tar_type 非必传参数,固定值:GZIP,返回格式为.gzip的压缩包账单。不传则默认为数据流形式。 - * @param deviceInfo 设备号 device_info 非必传参数,终端设备号 - * @return 保存到本地的临时文件 - */ - @Operation(summary = "下载对账单") - @GetMapping("/downloadBill/{billDate}/{billType}/{tarType}/{deviceInfo}") - public WxPayBillResult downloadBill(@PathVariable String billDate, @PathVariable String billType, - @PathVariable String tarType, @PathVariable String deviceInfo) throws WxPayException { - return this.wxService.downloadBill(billDate, billType, tarType, deviceInfo); - } - - @Operation(summary = "下载对账单") - @PostMapping("/downloadBill") - public WxPayBillResult downloadBill(WxPayDownloadBillRequest wxPayDownloadBillRequest) throws WxPayException { - return this.wxService.downloadBill(wxPayDownloadBillRequest); - } - - /** - *
-     * 提交刷卡支付
-     * 文档地址:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10&index=1
-     * 应用场景:
-     * 收银员使用扫码设备读取微信用户刷卡授权码以后,二维码或条码信息传送至商户收银台,由商户收银台或者商户后台调用该接口发起支付。
-     * 提醒1:提交支付请求后微信会同步返回支付结果。当返回结果为“系统错误”时,商户系统等待5秒后调用【查询订单API】,查询支付实际交易结果;当返回结果为“USERPAYING”时,商户系统可设置间隔时间(建议10秒)重新查询支付结果,直到支付成功或超时(建议30秒);
-     * 提醒2:在调用查询接口返回后,如果交易状况不明晰,请调用【撤销订单API】,此时如果交易失败则关闭订单,该单不能再支付成功;如果交易成功,则将扣款退回到用户账户。当撤销无返回或错误时,请再次调用。注意:请勿扣款后立即调用【撤销订单API】,建议至少15秒后再调用。撤销订单API需要双向证书。
-     * 接口地址:   https://api.mch.weixin.qq.com/pay/micropay
-     * 是否需要证书:不需要。
-     * 
- */ - @Operation(summary = "提交刷卡支付") - @PostMapping("/micropay") - public WxPayMicropayResult micropay(@RequestBody WxPayMicropayRequest request) throws WxPayException { - return this.wxService.micropay(request); - } - - /** - *
-     * 撤销订单API
-     * 文档地址:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_11&index=3
-     * 应用场景:
-     *  支付交易返回失败或支付系统超时,调用该接口撤销交易。如果此订单用户支付失败,微信支付系统会将此订单关闭;如果用户支付成功,微信支付系统会将此订单资金退还给用户。
-     *  注意:7天以内的交易单可调用撤销,其他正常支付的单如需实现相同功能请调用申请退款API。提交支付交易后调用【查询订单API】,没有明确的支付结果再调用【撤销订单API】。
-     *  调用支付接口后请勿立即调用撤销订单API,建议支付后至少15s后再调用撤销订单接口。
-     *  接口链接 :https://api.mch.weixin.qq.com/secapi/pay/reverse
-     *  是否需要证书:请求需要双向证书。
-     * 
- */ - @Operation(summary = "撤销订单") - @PostMapping("/reverseOrder") - public WxPayOrderReverseResult reverseOrder(@RequestBody WxPayOrderReverseRequest request) throws WxPayException { - return this.wxService.reverseOrder(request); - } - - @Operation(summary = "获取沙箱环境签名key") - @GetMapping("/getSandboxSignKey") - public String getSandboxSignKey() throws WxPayException { - return this.wxService.getSandboxSignKey(); - } - - @Operation(summary = "发放代金券") - @PostMapping("/sendCoupon") - public WxPayCouponSendResult sendCoupon(@RequestBody WxPayCouponSendRequest request) throws WxPayException { - return this.wxService.sendCoupon(request); - } - - @Operation(summary = "查询代金券批次") - @PostMapping("/queryCouponStock") - public WxPayCouponStockQueryResult queryCouponStock(@RequestBody WxPayCouponStockQueryRequest request) - throws WxPayException { - return this.wxService.queryCouponStock(request); - } - - @Operation(summary = "查询代金券信息") - @PostMapping("/queryCouponInfo") - public WxPayCouponInfoQueryResult queryCouponInfo(@RequestBody WxPayCouponInfoQueryRequest request) - throws WxPayException { - return this.wxService.queryCouponInfo(request); - } - - @Operation(summary = "拉取订单评价数据") - @PostMapping("/queryComment") - public String queryComment(Date beginDate, Date endDate, Integer offset, Integer limit) throws WxPayException { - return this.wxService.queryComment(beginDate, endDate, offset, limit); - } - -} \ No newline at end of file diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/error/ErrorController.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/error/ErrorController.java deleted file mode 100644 index a26dcc5..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/error/ErrorController.java +++ /dev/null @@ -1,21 +0,0 @@ -package org.wfc.payment.wxpay.error; - -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; - -@Controller -@RequestMapping("/error") -public class ErrorController { - - @GetMapping(value = "/404") - public String error404() { - return "error"; - } - - @GetMapping(value = "/500") - public String error500() { - return "error"; - } - -} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/error/ErrorPageConfiguration.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/error/ErrorPageConfiguration.java deleted file mode 100644 index a91306f..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/error/ErrorPageConfiguration.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.wfc.payment.wxpay.error; - -import org.springframework.boot.web.server.ErrorPage; -import org.springframework.boot.web.server.ErrorPageRegistrar; -import org.springframework.boot.web.server.ErrorPageRegistry; -import org.springframework.http.HttpStatus; -import org.springframework.stereotype.Component; - -@Component -public class ErrorPageConfiguration implements ErrorPageRegistrar { - @Override - public void registerErrorPages(ErrorPageRegistry errorPageRegistry) { - errorPageRegistry.addErrorPages( - new ErrorPage(HttpStatus.NOT_FOUND, "/error/404"), - new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500") - ); - } - -} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/mapper/UWxPayOrderMapper.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/mapper/UWxPayOrderMapper.java deleted file mode 100644 index a984d13..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/mapper/UWxPayOrderMapper.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.wfc.payment.wxpay.mapper; - -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.wfc.payment.wxpay.model.UWxPayOrderModel; - -@Mapper -public interface UWxPayOrderMapper { - - void insertOrder(UWxPayOrderModel uWxPayOrder); - - void updateOrder(UWxPayOrderModel uWxPayOrder); - - UWxPayOrderModel selectOrderByOutTradeNo(@Param("outTradeNo") String outTradeNo); - - UWxPayOrderModel selectOrderById(@Param("id") Long id); -} \ No newline at end of file diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/model/UWxPayOrderModel.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/model/UWxPayOrderModel.java deleted file mode 100644 index 6cdb1d4..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/model/UWxPayOrderModel.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.wfc.payment.wxpay.model; - -import javax.persistence.*; -import java.util.Date; -import lombok.Data; - -@Data -@Entity -public class UWxPayOrderModel { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - private Long userId; - private String outTradeNo; - private String trancationId; - private String tradeStatus; - private Long totalAmount; - private String subject; - private String body; - private String createBy; - private Date createTime; - private String updateBy; - private Date updateTime; - - // Getters and Setters -} \ No newline at end of file diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/service/IWxPayNotifyOrderService.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/service/IWxPayNotifyOrderService.java deleted file mode 100644 index 0ac17f9..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/service/IWxPayNotifyOrderService.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.wfc.payment.wxpay.service; - -import java.util.Map; - -public interface IWxPayNotifyOrderService { - boolean handleWxPayNotifyOrder(Map params); -} \ No newline at end of file diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/service/IWxPayNotifyRefundService.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/service/IWxPayNotifyRefundService.java deleted file mode 100644 index 1fd98f9..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/service/IWxPayNotifyRefundService.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.wfc.payment.wxpay.service; - -import java.util.Map; - -public interface IWxPayNotifyRefundService { - boolean handleWxPayNotifyRefund(Map params); -} \ No newline at end of file diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/service/IWxPayNotifyScanpayService.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/service/IWxPayNotifyScanpayService.java deleted file mode 100644 index f8d49d7..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/service/IWxPayNotifyScanpayService.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.wfc.payment.wxpay.service; - -import java.util.Map; - -public interface IWxPayNotifyScanpayService { - boolean handleWxPayNotifyScanpay(Map params); -} \ No newline at end of file diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/service/impl/WxPayNotifyOrderServiceImpl.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/service/impl/WxPayNotifyOrderServiceImpl.java deleted file mode 100644 index c17f523..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/service/impl/WxPayNotifyOrderServiceImpl.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.wfc.payment.wxpay.service.impl; - -import java.util.Map; -import org.springframework.stereotype.Service; -import org.wfc.payment.wxpay.mapper.UWxPayOrderMapper; -import org.wfc.payment.wxpay.model.UWxPayOrderModel; -import lombok.AllArgsConstructor; -import java.util.Date; -import org.wfc.payment.wxpay.utils.VerifySignUtils; -import org.wfc.payment.wxpay.service.IWxPayNotifyOrderService; - -@AllArgsConstructor -@Service -public class WxPayNotifyOrderServiceImpl implements IWxPayNotifyOrderService { - - private final UWxPayOrderMapper wxpayOrderMapper; - private final VerifySignUtils verifySignUtils; - - public boolean handleWxPayNotifyOrder(Map params) { - // 验证签名 - boolean signVerified = verifySignUtils.verifySignature(params); - if (signVerified) { - // 处理业务逻辑,例如更新订单状态 - String outTradeNo = params.get("out_trade_no"); - String tradeStatus = params.get("trade_state"); - Long totalAmount = new Long(params.get("total_fee")); // 微信支付金额单位为分 - String subject = params.get("subject"); - String body = params.get("body"); - - UWxPayOrderModel order = wxpayOrderMapper.selectOrderByOutTradeNo(outTradeNo); - if (order == null) { - order = new UWxPayOrderModel(); - order.setOutTradeNo(outTradeNo); - order.setCreateTime(new Date()); - wxpayOrderMapper.insertOrder(order); - } - order.setTradeStatus(tradeStatus); - order.setTotalAmount(totalAmount); - order.setSubject(subject); - order.setBody(body); - order.setUpdateTime(new Date()); - - wxpayOrderMapper.updateOrder(order); - - return "SUCCESS".equals(tradeStatus); - } - return false; - } -} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/service/impl/WxPayNotifyRefundServiceImpl.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/service/impl/WxPayNotifyRefundServiceImpl.java deleted file mode 100644 index e2dcf74..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/service/impl/WxPayNotifyRefundServiceImpl.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.wfc.payment.wxpay.service.impl; - -import java.util.Map; - -import org.springframework.stereotype.Service; -import org.wfc.payment.wxpay.mapper.UWxPayOrderMapper; -import org.wfc.payment.wxpay.model.UWxPayOrderModel; -import lombok.AllArgsConstructor; -import java.util.Date; -import org.wfc.payment.wxpay.utils.VerifySignUtils; -import org.wfc.payment.wxpay.service.IWxPayNotifyRefundService; - -@AllArgsConstructor -@Service -public class WxPayNotifyRefundServiceImpl implements IWxPayNotifyRefundService { - private final UWxPayOrderMapper wxpayOrderMapper; - private final VerifySignUtils verifySignUtils; - - public boolean handleWxPayNotifyRefund(Map params) { - // 验证签名 - boolean signVerified = verifySignUtils.verifySignature(params); - if (signVerified) { - // 处理业务逻辑,例如更新订单状态 - String outTradeNo = params.get("out_trade_no"); - String tradeStatus = params.get("trade_status"); - Long totalAmount = new Long(params.get("total_fee")); // 微信支付金额单位为分 - String subject = params.get("subject"); - String body = params.get("body"); - - UWxPayOrderModel order = wxpayOrderMapper.selectOrderByOutTradeNo(outTradeNo); - if (order == null) { - order = new UWxPayOrderModel(); - order.setOutTradeNo(outTradeNo); - order.setCreateTime(new Date()); - wxpayOrderMapper.insertOrder(order); - } - order.setTradeStatus(tradeStatus); - order.setTotalAmount(totalAmount); - order.setSubject(subject); - order.setBody(body); - order.setUpdateTime(new Date()); - - wxpayOrderMapper.updateOrder(order); - - return "SUCCESS".equals(tradeStatus); - } - return false; - } -} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/service/impl/WxPayNotifyScanpayServiceImpl.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/service/impl/WxPayNotifyScanpayServiceImpl.java deleted file mode 100644 index 5ef4485..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/service/impl/WxPayNotifyScanpayServiceImpl.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.wfc.payment.wxpay.service.impl; - -import java.util.Map; - -import org.springframework.stereotype.Service; -import org.wfc.payment.wxpay.mapper.UWxPayOrderMapper; -import org.wfc.payment.wxpay.model.UWxPayOrderModel; -import org.wfc.payment.wxpay.service.IWxPayNotifyScanpayService; - -import lombok.AllArgsConstructor; -import java.util.Date; -import org.wfc.payment.wxpay.utils.VerifySignUtils; - -@AllArgsConstructor -@Service -public class WxPayNotifyScanpayServiceImpl implements IWxPayNotifyScanpayService { - private final UWxPayOrderMapper wxpayOrderMapper; - private final VerifySignUtils verifySignUtils; - - public boolean handleWxPayNotifyScanpay(Map params) { - // 验证签名 - boolean signVerified = verifySignUtils.verifySignature(params); - if (signVerified) { - // 处理业务逻辑,例如更新订单状态 - String outTradeNo = params.get("out_trade_no"); - String tradeStatus = params.get("trade_status"); - Long totalAmount = new Long(params.get("total_fee")); // 微信支付金额单位为分 - String subject = params.get("subject"); - String body = params.get("body"); - - UWxPayOrderModel order = wxpayOrderMapper.selectOrderByOutTradeNo(outTradeNo); - if (order == null) { - order = new UWxPayOrderModel(); - order.setOutTradeNo(outTradeNo); - order.setCreateTime(new Date()); - wxpayOrderMapper.insertOrder(order); - } - order.setTradeStatus(tradeStatus); - order.setTotalAmount(totalAmount); - order.setSubject(subject); - order.setBody(body); - order.setUpdateTime(new Date()); - - wxpayOrderMapper.updateOrder(order); - - return "SUCCESS".equals(tradeStatus); - } - return false; - } -} diff --git a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/utils/VerifySignUtils.java b/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/utils/VerifySignUtils.java deleted file mode 100644 index 5ef2f35..0000000 --- a/wfc-modules/wfc-payment/src/main/java/org/wfc/payment/wxpay/utils/VerifySignUtils.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.wfc.payment.wxpay.utils; - -import java.security.KeyFactory; -import java.security.PrivateKey; -import java.security.Signature; -import java.security.SignatureException; -import java.security.spec.X509EncodedKeySpec; -import java.util.ArrayList; -import java.nio.charset.StandardCharsets; -import java.util.Base64; -import java.util.Map; -import java.util.Collections; -import java.util.List; -import java.security.PublicKey; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.wfc.payment.wxpay.config.WxPayProperties; - -@Component -public class VerifySignUtils { - - private final WxPayProperties wxpayProperties; - - @Autowired - public VerifySignUtils(WxPayProperties wxpayProperties) { - this.wxpayProperties = wxpayProperties; - } - - public static String sign(String data, PrivateKey privateKey) throws SignatureException { - if (data == null || privateKey == null) { - throw new IllegalArgumentException("Data and private key cannot be null"); - } - try { - Signature signature = Signature.getInstance("SHA256withRSA"); - signature.initSign(privateKey); - signature.update(data.getBytes(StandardCharsets.UTF_8)); - byte[] signBytes = signature.sign(); - return Base64.getEncoder().encodeToString(signBytes); - } catch (Exception e) { - throw new SignatureException("Failed to sign data", e); - } - } - - public static boolean verify(String data, String sign, PublicKey publicKey) throws SignatureException { - if (data == null || sign == null || publicKey == null) { - throw new IllegalArgumentException("Data, sign and public key cannot be null"); - } - try { - Signature signature = Signature.getInstance("SHA256withRSA"); - signature.initVerify(publicKey); - signature.update(data.getBytes(StandardCharsets.UTF_8)); - byte[] signBytes = Base64.getDecoder().decode(sign); - return signature.verify(signBytes); - } catch (Exception e) { - throw new SignatureException("Failed to verify signature", e); - } - } - - public boolean verifySignature(Map params) { - if (params == null || params.isEmpty()) { - return false; - } - - // Extract signature parameter - String sign = params.remove("sign"); - if (sign == null) { - return false; - } - - // Sort parameters - List keys = new ArrayList<>(params.keySet()); - Collections.sort(keys); - - // Build parameter string - StringBuilder data = new StringBuilder(); - for (String key : keys) { - String value = params.get(key); - if (value != null) { - data.append(key) - .append("=") - .append(value) - .append("&"); - } - } - - // Remove last '&' - if (data.length() > 0) { - data.setLength(data.length() - 1); - } - - try { - byte[] keyBytes = Base64.getDecoder().decode(wxpayProperties.getMchKey()); - X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); - KeyFactory keyFactory = KeyFactory.getInstance("RSA"); - PublicKey publicKey = keyFactory.generatePublic(keySpec); - return verify(data.toString(), sign, publicKey); - } catch (Exception e) { - e.printStackTrace(); - return false; - } - } -} diff --git a/wfc-modules/wfc-payment/src/main/resources/application.yml b/wfc-modules/wfc-payment/src/main/resources/application.yml index ef29c56..6d420e5 100644 --- a/wfc-modules/wfc-payment/src/main/resources/application.yml +++ b/wfc-modules/wfc-payment/src/main/resources/application.yml @@ -1,6 +1,5 @@ # spring配置 spring: - redis: host: wfc-redis port: 6379 @@ -55,76 +54,13 @@ mybatis-plus: logic-delete-value: 1 logic-not-delete-value: 0 -wxpay: - appId: 121412414112 - mchId: 1131412414 - mchKey: 1525342aa - subAppId: #服务商模式下的子商户公众账号ID - subMchId: #服务商模式下的子商户号 - keyPath: /opt/wfc/conf/wxpay/wxpay_key.pem - useSandboxEnv: false - alipay: - appId: 121412414112 - privateKey: 1131412414 - publicKey: 1525342aa - notifyUrl: http://wfc-gateway:${GATEWAY_SERVER_PORT:8080}/alipay/notify - returnUrl: http://wfc-gateway:${GATEWAY_SERVER_PORT:8080}/alipay/return - signType: RSA2 - charset: utf-8 - gatewayUrl: https://openapi.alipaydev.com/gateway.do - logPath: /opt/wfc/logs/alipay/alipay.log - maxQueryRetry: 5 - queryDuration: 5 - maxCancelRetry: 3 - cancelDuration: 2 - heartbeatDelay: 5 - heartbeatDuration: 5 - storeId: - storeName: - supportEmail: - supportPhone: - -ccpay: - paymentUrl: https://api.paymentgateway.com/v1/payment - tokenUrl: https://api.paymentgateway.com/v1/token - queryUrl: https://api.paymentgateway.com/v1/query - refundUrl: https://api.paymentgateway.com/v1/refund - apiKey: api-key - merchantId: merchant-id - currency: USD - timeout: 30 - callbackUrl: https://wfc-gateway:${GATEWAY_SERVER_PORT:8080}/payment/callback - -unionpay: - merId: 700000000000001 - keyPrivateCert: /opt/wfc/conf/cert/unionpay/wfc-union.pfx - keyPrivateCertPwd: 123456 - signCertType: PKCS12 - encryptCertPath: /opt/wfc/conf/cert/unionpay/wfc-union.cer - acpMiddleCert: /opt/wfc/conf/cert/unionpay/wfc-middle.cer - acpRootCert: /opt/wfc/conf/cert/unionpay/wfc-root.cer - frontUrl: https://gateway.test.95516.com/gateway/api/frontTransReq.do - backUrl: http://wfc-gateway:${GATEWAY_SERVER_PORT:8080}/unionpay/notify - signMethod: 01 - version: 5.1.0 - channelType: 07 - accessType: 0 - currencyCode: 156 - bizType: 000201 - txnType: 01 - txnSubType: 01 - payTimeout: 30 - queryTimeout: 30 - refundTimeout: 30 - frontFailUrl: http://wfc-gateway:${GATEWAY_SERVER_PORT:8080}/unionpay/fail - frontSuccessUrl: http://wfc-gateway:${GATEWAY_SERVER_PORT:8080}/unionpay/success - frontBackUrl: http://wfc-gateway:${GATEWAY_SERVER_PORT:8080}/unionpay/front - backBackUrl: http://wfc-gateway:${GATEWAY_SERVER_PORT:8080}/unionpay/back - frontNotifyUrl: http://wfc-gateway:${GATEWAY_SERVER_PORT:8080}/unionpay/front/notify - backNotifyUrl: http://wfc-gateway:${GATEWAY_SERVER_PORT:8080}/unionpay/back/notify - refundNotifyUrl: http://wfc-gateway:${GATEWAY_SERVER_PORT:8080}/unionpay/refund/notify - queryNotifyUrl: http://wfc-gateway:${GATEWAY_SERVER_PORT:8080}/unionpay/query/notify - refundSuccessUrl: http://wfc-gateway:${GATEWAY_SERVER_PORT:8080}/unionpay/refund/success - refundFailUrl: http://wfc-gateway:${GATEWAY_SERVER_PORT:8080}/unionpay/refund/fail - querySuccessUrl: \ No newline at end of file + appId: 9021000122699258 + privateKey: MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC7YAcIXV5GJlTWBOoBcrVG1zKxHunznSjYXwTS2DM3YgloxzKye4apfcmBDVnoL93m4QrJTtbiHYvu4yJjJfJsQEY+Wo44IczhDypyu+Il6JpQOwylTs94/+3aaQ1wThsDaGs8edaFGteuw+1pUVl4nxF00fS1VoIR30riqAGFAXrPhcSA6Y9c8HK1htxCelICnPzjpqC4s8ZjrjS7FoyHP2ZAay5fx1VEtah30E4RvycFfV/i2+k3JGFOSeevdCx6Ufu+9Y/RaG4Sh84QuYRQUhAHUswlFDHpRrAnxHzt0zDkOkg3BrCT7vMtBbSOP9BdIhpVTaZm4diQdNbLSl4hAgMBAAECggEAKb1Xc7aQ1KGfTlmj4xSxawlvImOXjAwbWC+6fFlq91BgdjXBhl7b/Y+mvpfBymY3UUIaTAPC/HXGgT2ZoGqImTKsMyGrArgM0qm1M//EfdtV3L96rqxirTqduoSiWL0daWHuWXduoRH8r9K3ZTmY67TLh7FpiKevq9mI7fqs8/qgq5QAN4UPFb3Cq9hDNTU4l6+Bywdg1KkwJ2Jc98SlrIdVl+1eCMAgueLR0aNHTobyPBZ/KfwGRV0OQ3QqjLVgL3zlbzuylYhaZqPgxxd46vgWwkyMiiv7u2OyCetq4LFd+tcNDz0Yqk6rK9/S0oxbN8NM5DLkpwFh/433BoPS3QKBgQD/dsxNr2PYdPLp6pOvw7H2AFMH8CkwTlRg+2f/0fgQF14rJwZgEU6fL5A2JvQeRRC5mCff2m5tDqrS321JNyH/JIKJ+4J8I34GEo/kSCHL3RmyvJGQOQ/EpEyxvP8BV3ob6UO3LR58DOGlJr8eTsr3Y8o9cAMuknCNxvsd2LvybwKBgQC7xKkx4KIPBny6sCOtChOkgIrY3hOCi+ZsHQVESXKzeku0NkH/qrAG+S9pb1XCzXdM2HrzkMeuz6tqi+2TY8nORyY2DZHNW7FqzkAiZ/NO2AgGIlALq1ZfJZke2MxgtBnxSsQ03gfXP9opu/FsLH9a+s6edfHPvKD4kHxlLBfAbwKBgQDYvr6QmuKn4HHJLZGoau0uvw+ziHwp1AubTTLrxgYmAO2Qx0eNcqG2RfChQWOV2xtZnFMYhodyWCNvTsm2eOSLSTrIP3ByStq95DnZganLAgivsXX/W6qZOJ0poCTryoB79enSHKHktjksmjdFS6zBQRVyEvtgJDcC03Rz2lN8WQKBgQCCoJE4otb7bv7s/ccEBeOeaNKvhue5xUwbYKEeXZ6PYAA0sh5+GCf34flq90qJiFl7u4rl0Y4pfk35hLlV9XEasYLSzePmIuktrakOhpTNABus8MgRJjSjYsvAmwCsMf9uTx5qzSBVThWfPSH6qIY9LAj8Un9UjxzJb/Mqi19GvwKBgQC0/KB+3robTqy9KOV4iEKJ4kmnXDRu7ecpMyc8k5HzpolIHcXLZHkBK9pMCXBQ9Kwy6BjRGNnUZOahS+tvnMcjHpwdhu90r7D51GXW/+PeFtphYTscFhHv1yuWbbojzhKf69pZnsVmyllIBqRgtbkS2WNHxWo/peCg47TcLaQNMA== + publicKey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhBZoE6p1TKpd/WsAJRTA2D6yUTzqLmZ73scxbPxxKwPIg2ys2Ap21u/lVmqBWO9Wf2Z7wUwr/6BP1PQqVpg0GAqU3yjjZ0LGfBitzMBMbGrlOLqJQ3PKgnUNmnOdLR4FlHCAjKtuyxjHkxBTHg/L4punk4lkFJQD8YvzFrYalS6WYw5j1/oq080NbcjPirPCRlsU7MRraQuUqSTdPwm2iHkroKwCEbGv+RtNJCfOkKNQVtRFFgPGMhU4nQ620gdfzsGJsNFKVJnD5SjeDWniBAbaGaVF4rEfKJPe6+XrcMg3h+9Fz+A2IU1KCCoth2neEZEaU1t0KBGxXIuo4efi/QIDAQAB + appCertPath: \u5E94\u7528\u516C\u94A5\u8BC1\u4E66 + aliPayCertPath: \u652F\u4ED8\u5B9D\u516C\u94A5\u8BC1\u4E66 + aliPayRootCertPath: \u652F\u4ED8\u5B9D\u6839\u8BC1\u4E66 + serverUrl: https://openapi-sandbox.dl.alipaydev.com/gateway.do + domain: http://localhost:8085 + testDomain: http://129.204.171.210:8085 diff --git a/wfc-modules/wfc-payment/src/main/resources/mapper/payment/UAlipayOrderMapper.xml b/wfc-modules/wfc-payment/src/main/resources/mapper/payment/UAlipayOrderMapper.xml deleted file mode 100644 index 189bde9..0000000 --- a/wfc-modules/wfc-payment/src/main/resources/mapper/payment/UAlipayOrderMapper.xml +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - - - - - - - INSERT INTO u_alipay_order (out_trade_no, trade_status, total_amount, subject, body, create_time, update_time) - VALUES (#{outTradeNo}, #{tradeStatus}, #{totalAmount}, #{subject}, #{body}, #{createTime}, #{updateTime}) - - - - UPDATE u_alipay_order - SET trade_status = #{tradeStatus}, total_amount = #{totalAmount}, subject = #{subject}, body = #{body}, update_time = #{updateTime} - WHERE out_trade_no = #{outTradeNo} - - - \ No newline at end of file diff --git a/wfc-modules/wfc-payment/src/main/resources/mapper/payment/UCreditCardOrderMapper.xml b/wfc-modules/wfc-payment/src/main/resources/mapper/payment/UCreditCardOrderMapper.xml deleted file mode 100644 index 3608095..0000000 --- a/wfc-modules/wfc-payment/src/main/resources/mapper/payment/UCreditCardOrderMapper.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - INSERT INTO u_credit_card_order (transaction_id, user_id, order_id, amount, currency, status, payment_time, card_type, card_holder_name, billing_address, card_last_four, gateway_response) - VALUES (#{transactionId}, #{userId}, #{orderId}, #{amount}, #{currency}, #{status}, #{paymentTime}, #{cardType}, #{cardHolderName}, #{billingAddress}, #{cardLastFour}, #{gatewayResponse}) - - - - - - \ No newline at end of file diff --git a/wfc-modules/wfc-payment/src/main/resources/mapper/payment/UCreditCardTokenMapper.xml b/wfc-modules/wfc-payment/src/main/resources/mapper/payment/UCreditCardTokenMapper.xml deleted file mode 100644 index 85b9996..0000000 --- a/wfc-modules/wfc-payment/src/main/resources/mapper/payment/UCreditCardTokenMapper.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - INSERT INTO u_credit_card_token (user_id, token, card_last_four, card_type, created_at) - VALUES (#{userId}, #{token}, #{cardLastFour}, #{cardType}, #{createdAt}) - - - - - \ No newline at end of file diff --git a/wfc-modules/wfc-payment/src/main/resources/mapper/payment/UWxPayOrderMapper.xml b/wfc-modules/wfc-payment/src/main/resources/mapper/payment/UWxPayOrderMapper.xml deleted file mode 100644 index 9490700..0000000 --- a/wfc-modules/wfc-payment/src/main/resources/mapper/payment/UWxPayOrderMapper.xml +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - - - - - - - out_trade_no, - INSERT INTO u_wxpay_order (out_trade_no, trancation_id, trade_status, total_amount, subject, body, create_time, update_time) - VALUES (#{outTradeNo}, #{trancationId}, #{tradeStatus}, #{totalAmount}, #{subject}, #{body}, #{createTime}, #{updateTime}) - - - - UPDATE u_wxpay_order - SET trade_status = #{tradeStatus}, total_amount = #{totalAmount}, subject = #{subject}, body = #{body}, update_time = #{updateTime} - WHERE out_trade_no = #{outTradeNo} - - - \ No newline at end of file diff --git a/wfc-modules/wfc-user/src/main/java/org/wfc/user/controller/UOrderController.java b/wfc-modules/wfc-user/src/main/java/org/wfc/user/controller/UOrderController.java index afa8485..7c93c35 100644 --- a/wfc-modules/wfc-user/src/main/java/org/wfc/user/controller/UOrderController.java +++ b/wfc-modules/wfc-user/src/main/java/org/wfc/user/controller/UOrderController.java @@ -13,9 +13,11 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.wfc.common.core.domain.LoginUser; +import org.wfc.common.core.domain.R; import org.wfc.common.core.web.controller.BaseController; import org.wfc.common.core.web.domain.AjaxResult; import org.wfc.common.core.web.page.TableDataInfo; +import org.wfc.common.security.annotation.InnerAuth; import org.wfc.common.security.utils.SecurityUtils; import org.wfc.user.domain.UOrder; import org.wfc.user.domain.UPackage; @@ -96,8 +98,8 @@ public class UOrderController extends BaseController { } @PostMapping - public AjaxResult add(@RequestBody UOrder uOrder) { - return toAjax(uOrderService.saveOrder(uOrder)); + public R add(@RequestBody UOrder uOrder) { + return R.ok(uOrderService.saveOrder(uOrder)); } @PutMapping @@ -110,4 +112,9 @@ public class UOrderController extends BaseController { return toAjax(uOrderService.removeByIds(CollUtil.newArrayList(ids))); } + @InnerAuth + @PostMapping("paySuccess/{id}") + public AjaxResult paySuccess(@PathVariable("id") Long id) { + return toAjax(uOrderService.paySuccess(id)); + } } diff --git a/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/IUOrderService.java b/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/IUOrderService.java index beaab53..79f5102 100644 --- a/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/IUOrderService.java +++ b/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/IUOrderService.java @@ -13,6 +13,7 @@ import com.baomidou.mybatisplus.extension.service.IService; */ public interface IUOrderService extends IService { - boolean saveOrder(UOrder order); + Long saveOrder(UOrder order); + boolean paySuccess(Long orderId); } diff --git a/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/impl/UOrderServiceImpl.java b/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/impl/UOrderServiceImpl.java index 6db857b..0e778c1 100644 --- a/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/impl/UOrderServiceImpl.java +++ b/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/impl/UOrderServiceImpl.java @@ -15,6 +15,7 @@ import org.wfc.user.api.IWifiApi; import org.wfc.user.api.omada.domain.convert.OmadaConvert; import org.wfc.user.api.omada.domain.dto.ClientRateLimitSettingDto; import org.wfc.user.domain.UAccount; +import org.wfc.user.domain.UBillRule; import org.wfc.user.domain.UClient; import org.wfc.user.domain.UOrder; import org.wfc.user.domain.UPackage; @@ -22,6 +23,7 @@ import org.wfc.user.domain.URateLimit; import org.wfc.user.domain.constant.OrderStatusEnum; import org.wfc.user.domain.constant.OrderTypeEnum; import org.wfc.user.domain.constant.PeriodTypeEnum; +import org.wfc.user.mapper.UBillRuleMapper; import org.wfc.user.mapper.UOrderMapper; import org.wfc.user.service.IUAccountService; import org.wfc.user.service.IUClientService; @@ -58,14 +60,21 @@ public class UOrderServiceImpl extends ServiceImpl impleme @Autowired private IUClientService clientService; + @Autowired + private UBillRuleMapper billRuleMapper; + @Autowired private IWifiApi wifiApi; - public void paySuccess(Long orderId) { + @Override + public boolean paySuccess(Long orderId) { // 支付成功回调(预留) // 更新当前订单状态为已支付 UOrder order = this.getById(orderId); + if (OrderStatusEnum.PAID.getCode().equals(order.getStatus())) { + return false; + } order.setStatus(OrderStatusEnum.PAID.getCode()); this.updateById(order); @@ -109,7 +118,7 @@ public class UOrderServiceImpl extends ServiceImpl impleme wifiApi.updateClientRateLimitSetting(client.getSiteId(), client.getClientMac(), clientRateLimitSetting); } } - + return true; } private void callbackPackage(UOrder order, UAccount account) { @@ -156,14 +165,20 @@ public class UOrderServiceImpl extends ServiceImpl impleme } @Override - public boolean saveOrder(UOrder order) { + public Long saveOrder(UOrder order) { order.setUserId(SecurityUtils.getUserId()); order.setStatus(OrderStatusEnum.UNPAID.getCode()); order.setOrderNo(System.currentTimeMillis() + StrUtil.EMPTY); this.save(order); - // 支付成功回调 - paySuccess(order.getId()); + List billRules = billRuleMapper.selectList(Wrappers.lambdaQuery()); + billRules.stream().findFirst().ifPresent(billRule -> { + // 测试 + if (billRule.getTraffic() == 1) { + // 支付成功回调 + paySuccess(order.getId()); + } + }); - return true; + return order.getId(); } }