fix: 支付模块调整和对接
This commit is contained in:
8
pom.xml
8
pom.xml
@@ -39,6 +39,7 @@
|
||||
<swagger.core.version>1.6.2</swagger.core.version>
|
||||
<org.mapstruct.version>1.6.3</org.mapstruct.version>
|
||||
<mail.version>1.6.2</mail.version>
|
||||
<ijapy.version>2.9.11</ijapy.version>
|
||||
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
|
||||
<wfc.nacos.server>${env.NACOS_SERVER_NAME}</wfc.nacos.server>
|
||||
<wfc.nacos.port>${env.NACOS_SERVER_PORT}</wfc.nacos.port>
|
||||
@@ -335,6 +336,13 @@
|
||||
<artifactId>javax.mail</artifactId>
|
||||
<version>${mail.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 支付 -->
|
||||
<dependency>
|
||||
<groupId>com.github.javen205</groupId>
|
||||
<artifactId>IJPay-All</artifactId>
|
||||
<version>${ijapy.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
||||
@@ -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<Boolean> recordClientUser(@RequestBody UClientBo clientBo);
|
||||
|
||||
@PostMapping("/order/paySuccess/{id}")
|
||||
public R<Boolean> paySuccess(@PathVariable("id") Long id, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
|
||||
|
||||
@GetMapping(value = "/order/{id}")
|
||||
public R<UOrderVo> getOrderById(@PathVariable("id") Long id);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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<RemoteUUserSe
|
||||
public R<Boolean> recordClientUser(UClientBo clientBo) {
|
||||
return R.fail("根据设备mac保存或更新设备信息失败:" + throwable.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public R<Boolean> paySuccess(Long id, String source) {
|
||||
return R.fail("pay callback error:" + throwable.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public R<UOrderVo> getOrderById(Long id) {
|
||||
return R.fail("get order error:" + throwable.getMessage());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,52 +73,50 @@
|
||||
<artifactId>wfc-common-swagger</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- stripe for credit card pay -->
|
||||
<dependency>
|
||||
<groupId>com.stripe</groupId>
|
||||
<artifactId>stripe-java</artifactId>
|
||||
<version>20.0.0</version>
|
||||
<groupId>com.github.javen205</groupId>
|
||||
<artifactId>IJPay-WxPay</artifactId>
|
||||
<version>${ijapy.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- for WeChat Pay -->
|
||||
<dependency>
|
||||
<groupId>com.github.binarywang</groupId>
|
||||
<artifactId>weixin-java-pay</artifactId>
|
||||
<version>4.6.0</version>
|
||||
<groupId>com.github.javen205</groupId>
|
||||
<artifactId>IJPay-AliPay</artifactId>
|
||||
<version>${ijapy.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- for Ali Pay -->
|
||||
<dependency>
|
||||
<groupId>com.alipay.sdk</groupId>
|
||||
<artifactId>alipay-sdk-java</artifactId>
|
||||
<version>4.11.0.ALL</version>
|
||||
<groupId>com.github.javen205</groupId>
|
||||
<artifactId>IJPay-QQ</artifactId>
|
||||
<version>${ijapy.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- for Union Pay -->
|
||||
<dependency>
|
||||
<groupId>com.egzosn</groupId>
|
||||
<artifactId>pay-java-union</artifactId>
|
||||
<version>2.14.7</version>
|
||||
<groupId>com.github.javen205</groupId>
|
||||
<artifactId>IJPay-UnionPay</artifactId>
|
||||
<version>${ijapy.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Missing dependency for pay-java-web -->
|
||||
<dependency>
|
||||
<groupId>com.egzosn</groupId>
|
||||
<artifactId>pay-java-web-support</artifactId>
|
||||
<version>2.14.7</version>
|
||||
<groupId>com.github.javen205</groupId>
|
||||
<artifactId>IJPay-JDPay</artifactId>
|
||||
<version>${ijapy.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Swagger 依赖项 -->
|
||||
<dependency>
|
||||
<groupId>org.springdoc</groupId>
|
||||
<artifactId>springdoc-openapi-ui</artifactId>
|
||||
<version>1.6.14</version>
|
||||
<groupId>com.github.javen205</groupId>
|
||||
<artifactId>IJPay-PayPal</artifactId>
|
||||
<version>${ijapy.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.wfc</groupId>
|
||||
<artifactId>wfc-api-user</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.persistence</groupId>
|
||||
<artifactId>javax.persistence-api</artifactId>
|
||||
<version>2.2</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
@@ -136,13 +134,6 @@
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestEntries>
|
||||
<Implementation-Version>${wfc-modules-payment.version}</Implementation-Version>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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<String, String> params) {
|
||||
try {
|
||||
boolean result = alipayNotifyService.handleAlipayNotify(params);
|
||||
return result ? "success" : "failure";
|
||||
} catch (AlipayApiException e) {
|
||||
e.printStackTrace();
|
||||
return "failure";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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<String, String> params) throws AlipayApiException;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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<String, String> 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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/**");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package org.wfc.payment.domain;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>支付宝配置 Bean</p>
|
||||
*
|
||||
* @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;
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package org.wfc.payment.domain;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>JD配置 Bean</p>
|
||||
*
|
||||
* @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 + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package org.wfc.payment.domain;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>PayPal配置 Bean</p>
|
||||
*
|
||||
* @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 + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package org.wfc.payment.domain;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>云闪付配置 Bean</p>
|
||||
*
|
||||
* @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 + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package org.wfc.payment.domain;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>微信配置 Bean</p>
|
||||
*
|
||||
* @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 + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
package org.wfc.payment.domain;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>微信配置 Bean</p>
|
||||
*
|
||||
* @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 + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>支付宝支付拦截器</p>
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>微信支付拦截器</p>
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>支付宝支付 Demo</p>
|
||||
*
|
||||
* @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<UOrderVo> 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<String, String> 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<String, String> map = AliPayApi.toMap(request);
|
||||
for (Map.Entry<String, String> 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<String, String> map = AliPayApi.toMap(request);
|
||||
for (Map.Entry<String, String> 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<String, String> params = AliPayApi.toMap(request);
|
||||
|
||||
for (Map.Entry<String, String> 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<String, String> params = AliPayApi.toMap(request);
|
||||
|
||||
for (Map.Entry<String, String> 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";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.wfc.payment.ccpay.exception;
|
||||
package org.wfc.payment.pay.ccpay.exception;
|
||||
|
||||
public class RuntimeException extends Exception {
|
||||
|
||||
@@ -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 {
|
||||
@@ -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 {
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.wfc.payment.ccpay.model;
|
||||
package org.wfc.payment.pay.ccpay.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.wfc.payment.ccpay.model;
|
||||
package org.wfc.payment.pay.ccpay.model;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.wfc.payment.ccpay.model;
|
||||
package org.wfc.payment.pay.ccpay.model;
|
||||
|
||||
public class RefundRequest {
|
||||
private String transactionId;
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.wfc.payment.ccpay.model;
|
||||
package org.wfc.payment.pay.ccpay.model;
|
||||
|
||||
public class RefundResponse {
|
||||
private String status;
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.wfc.payment.ccpay.model;
|
||||
package org.wfc.payment.pay.ccpay.model;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.math.BigDecimal;
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.wfc.payment.ccpay.model;
|
||||
package org.wfc.payment.pay.ccpay.model;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.time.LocalDateTime;
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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 {
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
*
|
||||
* <p> 京东APP支付 </p>
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>微信支付 Demo</p>
|
||||
*
|
||||
* @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<String, String> 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<String, Object> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, Object> 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<String, String> 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<String, String> 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<String, Object> toMap = XmlUtil.xmlToMap(decrypt);
|
||||
System.out.println(toMap);
|
||||
return new AjaxResult().success(decrypt);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,297 @@
|
||||
/**
|
||||
*
|
||||
* <p>PayPal 支付示例</p>
|
||||
*
|
||||
* @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<String, Object> dataMap = new HashMap<>();
|
||||
dataMap.put("intent", "CAPTURE");
|
||||
|
||||
ArrayList<Map<String, Object>> list = new ArrayList<>();
|
||||
|
||||
Map<String, Object> amount = new HashMap<>();
|
||||
amount.put("currency_code", "USD");
|
||||
amount.put("value", "0.01");
|
||||
|
||||
Map<String, Object> itemMap = new HashMap<>();
|
||||
itemMap.put("amount", amount);
|
||||
|
||||
list.add(itemMap);
|
||||
|
||||
dataMap.put("purchase_units", list);
|
||||
|
||||
Map<String, String> card = new HashMap<>();
|
||||
card.put("name", "test buyer");
|
||||
card.put("number", "4231220385792723");
|
||||
card.put("security_code", "123");
|
||||
card.put("expiry", "2029-07");
|
||||
|
||||
Map<String, String> experienceContext = new HashMap<>();
|
||||
experienceContext.put("cancel_url", config.getDomain().concat(CANCEL_URL));
|
||||
experienceContext.put("return_url", config.getDomain().concat(RETURN_URL));
|
||||
Map<String, Map<String,String>> 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<Map<String, Object>> updateData = new ArrayList<>();
|
||||
|
||||
Map<String, Object> itemMap = new HashMap<>();
|
||||
itemMap.put("op", "replace");
|
||||
itemMap.put("path", "/purchase_units/@reference_id=='default'/amount");
|
||||
|
||||
Map<String, Object> 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<String, Object> map = new HashMap<>();
|
||||
map.put("invoice_id", PayKit.generateStr());
|
||||
map.put("note_to_payer", "test product");
|
||||
|
||||
Map<String, String> 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;
|
||||
}
|
||||
}
|
||||
@@ -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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> unionPayCall(HttpServletRequest request) {
|
||||
Map<String, String> params = new HashMap<>();
|
||||
Map<String, String[]> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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";
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>微信支付 Demo</p>
|
||||
*
|
||||
* @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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> packageParams = new HashMap<String, String>(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<String, String> 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<String, String> 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<String, String> prepayParams = new HashMap<String, String>(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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> params = new HashMap<String, String>(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<String, String> params = new HashMap<String, String>(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<String, String> params = new HashMap<String, String>(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<String, String> 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<ReceiverModel> list = new ArrayList<>();
|
||||
|
||||
list.add(ReceiverModel.builder()
|
||||
.type("PERSONAL_OPENID")
|
||||
.account("openid")
|
||||
.amount(66)
|
||||
.description("IJPay 分账")
|
||||
.build());
|
||||
|
||||
Map<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> xml = new HashMap<String, String>(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<String, String> 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<String, String> 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<String, String> params = WxPayKit.xmlToMap(xmlMsg);
|
||||
|
||||
String returnCode = params.get("return_code");
|
||||
|
||||
// 注意重复通知的情况,同一订单号可能收到多次通知,请注意一定先判断订单状态
|
||||
// 注意此处签名方式需与统一下单的签名类型一致
|
||||
if (WxPayKit.verifyNotify(params, WxPayApiConfigKit.getWxPayApiConfig().getPartnerKey(), SignType.HMACSHA256)) {
|
||||
if (WxPayKit.codeIsOk(returnCode)) {
|
||||
// 更新订单信息
|
||||
// 发送通知等
|
||||
Map<String, String> xml = new HashMap<String, String>(2);
|
||||
xml.put("return_code", "SUCCESS");
|
||||
xml.put("return_msg", "OK");
|
||||
return WxPayKit.toXml(xml);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
*
|
||||
* <p>微信支付 v3 接口示例</p>
|
||||
*
|
||||
* @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<String, List<String>> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<String, String> 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<Object, Object> 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<String, String> 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<String, String> 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<String, String> 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<RefundGoodsDetail> 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<String, String> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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<String, Object> 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<String, Object> app() {
|
||||
Map<String, Object> 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<String, Object> 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<String, Object> 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<String, Object> 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 是否成功
|
||||
* <p>
|
||||
* 业务处理在对应的PayMessageHandler里面处理,在哪里设置PayMessageHandler,详情查看{@link com.egzosn.pay.common.api.PayService#setPayMessageHandler(com.egzosn.pay.common.api.PayMessageHandler)}
|
||||
* <p>
|
||||
* 如果未设置 {@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<String, Object> 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());
|
||||
}
|
||||
}
|
||||
@@ -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 +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -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<UnionPayConfigStorage> 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<UnionPayConfigStorage> getPayService(ApyAccount apyAccount);
|
||||
}
|
||||
@@ -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 + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -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<Integer, ApyAccount> 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<Integer, ApyAccount> 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);
|
||||
}
|
||||
}
|
||||
@@ -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<Integer, PayResponse> 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;
|
||||
}
|
||||
}
|
||||
@@ -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<? extends PayConfigStorage> 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<? extends PayConfigStorage> getService() {
|
||||
return service;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<M extends PayMessage, S extends PayService<?>> implements PayMessageHandler<M, S> {
|
||||
//支付账户id
|
||||
private Integer payId;
|
||||
|
||||
protected BasePayMessageImpl(Integer payId) {
|
||||
this.payId = payId;
|
||||
}
|
||||
|
||||
public Integer getPayId() {
|
||||
return payId;
|
||||
}
|
||||
}
|
||||
@@ -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<UnionPayMessage, UnionPayService> {
|
||||
|
||||
public UnionPayMessageImpl(Integer payId) {
|
||||
super(payId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayOutMessage handle(UnionPayMessage payMessage, Map<String, Object> 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", "失败");
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串格式化
|
||||
* <p>
|
||||
* use: format("my name is {0}, and i like {1}!", "L.cm", "java")
|
||||
* <p>
|
||||
* 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("[ `·•<C2B7>\\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));
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
// }
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 查询订单(详见https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2)
|
||||
* 该接口提供所有微信支付订单的查询,商户可以通过查询订单接口主动查询订单状态,完成下一步的业务逻辑。
|
||||
* 需要调用查询接口的情况:
|
||||
* ◆ 当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知;
|
||||
* ◆ 调用支付接口后,返回系统错误或未知交易状态情况;
|
||||
* ◆ 调用被扫支付API,返回USERPAYING的状态;
|
||||
* ◆ 调用关单或撤销接口API之前,需确认支付状态;
|
||||
* 接口地址:https://api.mch.weixin.qq.com/pay/orderquery
|
||||
* </pre>
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 关闭订单
|
||||
* 应用场景
|
||||
* 以下情况需要调用关单接口:
|
||||
* 1. 商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付;
|
||||
* 2. 系统下单后,用户支付超时,系统退出不再受理,避免用户继续,请调用关单接口。
|
||||
* 注意:订单生成后不能马上调用关单接口,最短调用时间间隔为5分钟。
|
||||
* 接口地址:https://api.mch.weixin.qq.com/pay/closeorder
|
||||
* 是否需要证书: 不需要。
|
||||
* </pre>
|
||||
*
|
||||
* @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 <T> 请使用{@link com.github.binarywang.wxpay.bean.order}包下的类
|
||||
* @return 返回 {@link com.github.binarywang.wxpay.bean.order}包下的类对象
|
||||
*/
|
||||
@Operation(summary = "统一下单,并组装所需支付参数")
|
||||
@PostMapping("/createOrder")
|
||||
public <T> 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 微信支付-申请退款
|
||||
* 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
|
||||
* 接口链接:https://api.mch.weixin.qq.com/secapi/pay/refund
|
||||
* </pre>
|
||||
*
|
||||
* @param request 请求对象
|
||||
* @return 退款操作结果
|
||||
*/
|
||||
@Operation(summary = "Refund")
|
||||
@PostMapping("/refund")
|
||||
public WxPayRefundResult refund(@RequestBody WxPayRefundRequest request) throws WxPayException {
|
||||
return this.wxService.refund(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 微信支付-查询退款
|
||||
* 应用场景:
|
||||
* 提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用零钱支付的退款20分钟内到账,
|
||||
* 银行卡支付的退款3个工作日后重新查询退款状态。
|
||||
* 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5
|
||||
* 接口链接:https://api.mch.weixin.qq.com/pay/refundquery
|
||||
* </pre>
|
||||
*
|
||||
* 以下四个参数四选一
|
||||
*
|
||||
* @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<String, String> 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<String, String> 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<String, String> notifyResultMap = notifyResult.toMap();
|
||||
boolean result = wxPayNotifyScanpayService.handleWxPayNotifyScanpay(notifyResultMap);
|
||||
return result ? MSG_SUCCESS : MSG_FAILURE;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return MSG_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送微信红包给个人用户
|
||||
*
|
||||
* <pre>
|
||||
* 文档详见:
|
||||
* 发送普通红包 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
|
||||
* </pre>
|
||||
*
|
||||
* @param request 请求对象
|
||||
*/
|
||||
@Operation(summary = "发送红包")
|
||||
@PostMapping("/sendRedpack")
|
||||
public WxPaySendRedpackResult sendRedpack(@RequestBody WxPaySendRedpackRequest request) throws WxPayException {
|
||||
return this.wxService.getRedpackService().sendRedpack(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 查询红包记录
|
||||
* 用于商户对已发放的红包进行查询红包的具体信息,可支持普通红包和裂变包。
|
||||
* 请求Url https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo
|
||||
* 是否需要证书 是(证书及使用说明详见商户证书)
|
||||
* 请求方式 POST
|
||||
* </pre>
|
||||
*
|
||||
* @param mchBillNo 商户发放红包的商户订单号,比如10000098201411111234567890
|
||||
*/
|
||||
@Operation(summary = "查询红包")
|
||||
@GetMapping("/queryRedpack/{mchBillNo}")
|
||||
public WxPayRedpackQueryResult queryRedpack(@PathVariable String mchBillNo) throws WxPayException {
|
||||
return this.wxService.getRedpackService().queryRedpack(mchBillNo);
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 扫码支付模式一生成二维码的方法
|
||||
* 二维码中的内容为链接,形式为:
|
||||
* 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
|
||||
* </pre>
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 扫码支付模式一生成二维码的方法
|
||||
* 二维码中的内容为链接,形式为:
|
||||
* 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
|
||||
* </pre>
|
||||
*
|
||||
* @param productId 产品Id
|
||||
* @return 生成的二维码URL连接
|
||||
*/
|
||||
public String createScanPayQrcodeMode1(String productId) {
|
||||
return this.wxService.createScanPayQrcodeMode1(productId);
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 扫码支付模式二生成二维码的方法
|
||||
* 对应链接格式:weixin://wxpay/bizpayurl?sr=XXXXX。请商户调用第三方库将code_url生成二维码图片。
|
||||
* 该模式链接较短,生成的二维码打印到结账小票上的识别率较高。
|
||||
* 文档详见: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5
|
||||
* </pre>
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 交易保障
|
||||
* 应用场景:
|
||||
* 商户在调用微信支付提供的相关接口时,会得到微信支付返回的相关信息以及获得整个接口的响应时间。
|
||||
* 为提高整体的服务水平,协助商户一起提高服务质量,微信支付提供了相关接口调用耗时和返回信息的主动上报接口,
|
||||
* 微信支付可以根据商户侧上报的数据进一步优化网络部署,完善服务监控,和商户更好的协作为用户提供更好的业务体验。
|
||||
* 接口地址: https://api.mch.weixin.qq.com/payitil/report
|
||||
* 是否需要证书:不需要
|
||||
* </pre>
|
||||
*/
|
||||
@Operation(summary = "提交交易保障数据")
|
||||
@PostMapping("/report")
|
||||
public void report(@RequestBody WxPayReportRequest request) throws WxPayException {
|
||||
this.wxService.report(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 下载对账单
|
||||
* 商户可以通过该接口下载历史交易清单。比如掉单、系统错误等导致商户侧和微信侧数据不一致,通过对账单核对后可校正支付状态。
|
||||
* 注意:
|
||||
* 1、微信侧未成功下单的交易不会出现在对账单中。支付成功后撤销的交易会出现在对账单中,跟原支付单订单号一致,bill_type为REVOKED;
|
||||
* 2、微信在次日9点启动生成前一天的对账单,建议商户10点后再获取;
|
||||
* 3、对账单中涉及金额的字段单位为“元”。
|
||||
* 4、对账单接口只能下载三个月以内的账单。
|
||||
* 接口链接:https://api.mch.weixin.qq.com/pay/downloadbill
|
||||
* 详情请见: <a href=
|
||||
"https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_6">下载对账单</a>
|
||||
* </pre>
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 提交刷卡支付
|
||||
* 文档地址: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
|
||||
* 是否需要证书:不需要。
|
||||
* </pre>
|
||||
*/
|
||||
@Operation(summary = "提交刷卡支付")
|
||||
@PostMapping("/micropay")
|
||||
public WxPayMicropayResult micropay(@RequestBody WxPayMicropayRequest request) throws WxPayException {
|
||||
return this.wxService.micropay(request);
|
||||
}
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 撤销订单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
|
||||
* 是否需要证书:请求需要双向证书。
|
||||
* </pre>
|
||||
*/
|
||||
@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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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")
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package org.wfc.payment.wxpay.service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface IWxPayNotifyOrderService {
|
||||
boolean handleWxPayNotifyOrder(Map<String, String> params);
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package org.wfc.payment.wxpay.service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface IWxPayNotifyRefundService {
|
||||
boolean handleWxPayNotifyRefund(Map<String, String> params);
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package org.wfc.payment.wxpay.service;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface IWxPayNotifyScanpayService {
|
||||
boolean handleWxPayNotifyScanpay(Map<String, String> params);
|
||||
}
|
||||
@@ -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<String, String> 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;
|
||||
}
|
||||
}
|
||||
@@ -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<String, String> 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;
|
||||
}
|
||||
}
|
||||
@@ -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<String, String> 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;
|
||||
}
|
||||
}
|
||||
@@ -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<String, String> params) {
|
||||
if (params == null || params.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Extract signature parameter
|
||||
String sign = params.remove("sign");
|
||||
if (sign == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sort parameters
|
||||
List<String> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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:
|
||||
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
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.wfc.payment.alipay.mapper.UAlipayOrderMapper">
|
||||
<resultMap id="UAlipayOrderResultMap" type="org.wfc.payment.alipay.model.UAlipayOrderModel">
|
||||
<id property="id" column="id"/>
|
||||
<result property="userId" column="user_id"/>
|
||||
<result property="outTradeNo" column="out_trade_no"/>
|
||||
<result property="tradeStatus" column="trade_status"/>
|
||||
<result property="totalAmount" column="total_amount"/>
|
||||
<result property="subject" column="subject"/>
|
||||
<result property="body" column="body"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="updateTime" column="update_time"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="selectOrderByOutTradeNo" resultMap="UAlipayOrderResultMap">
|
||||
SELECT * FROM u_alipay_order WHERE out_trade_no = #{outTradeNo}
|
||||
</select>
|
||||
|
||||
<insert id="insertOrder">
|
||||
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})
|
||||
</insert>
|
||||
|
||||
<update id="updateOrder">
|
||||
UPDATE u_alipay_order
|
||||
SET trade_status = #{tradeStatus}, total_amount = #{totalAmount}, subject = #{subject}, body = #{body}, update_time = #{updateTime}
|
||||
WHERE out_trade_no = #{outTradeNo}
|
||||
</update>
|
||||
<select id="selectOrderById" parameterType="long" resultType="org.wfc.payment.alipay.model.UAlipayOrderModel" resultMap="UAlipayOrderResultMap">
|
||||
SELECT * FROM u_alipay_order WHERE id = #{id}
|
||||
</select>
|
||||
</mapper>
|
||||
@@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.wfc.payment.ccpay.mapper.UCreditCardOrderMapper">
|
||||
|
||||
<insert id="insertOrder" parameterType="org.wfc.payment.ccpay.model.UCreditCardOrder">
|
||||
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})
|
||||
</insert>
|
||||
|
||||
<select id="selectOrderById" parameterType="long" resultType="org.wfc.payment.ccpay.model.UCreditCardOrder">
|
||||
SELECT * FROM u_credit_card_order WHERE id = #{id}
|
||||
</select>
|
||||
|
||||
<!-- 其他需要的 SQL 映射 -->
|
||||
</mapper>
|
||||
@@ -1,14 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.wfc.payment.ccpay.mapper.UCreditCardTokenMapper">
|
||||
|
||||
<insert id="insertToken" parameterType="org.wfc.payment.ccpay.model.UCreditCardToken">
|
||||
INSERT INTO u_credit_card_token (user_id, token, card_last_four, card_type, created_at)
|
||||
VALUES (#{userId}, #{token}, #{cardLastFour}, #{cardType}, #{createdAt})
|
||||
</insert>
|
||||
|
||||
<select id="selectTokenByUserId" parameterType="long" resultType="org.wfc.payment.ccpay.model.UCreditCardToken">
|
||||
SELECT * FROM u_credit_card_token WHERE user_id = #{userId}
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -1,34 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.wfc.payment.wxpay.mapper.UWxPayOrderMapper">
|
||||
<resultMap id="UWxPayOrderResultMap" type="org.wfc.payment.wxpay.model.UWxPayOrderModel">
|
||||
<id property="id" column="id"/>
|
||||
<result property="userId" column="user_id"/>
|
||||
<result property="outTradeNo" column="out_trade_no"/>
|
||||
<result property="trancationId" column="trancation_id"/>
|
||||
<result property="tradeStatus" column="trade_status"/>
|
||||
<result property="totalAmount" column="total_amount"/>
|
||||
<result property="subject" column="subject"/>
|
||||
<result property="body" column="body"/>
|
||||
<result property="createTime" column="create_time"/>
|
||||
<result property="updateTime" column="update_time"/>
|
||||
</resultMap>
|
||||
|
||||
<select id="selectOrderByOutTradeNo" resultMap="UWxPayOrderResultMap">
|
||||
SELECT * FROM u_wxpay_order WHERE out_trade_no = #{outTradeNo}
|
||||
</select>
|
||||
|
||||
<insert id="insertOrder">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})
|
||||
</insert>
|
||||
|
||||
<update id="updateOrder">
|
||||
UPDATE u_wxpay_order
|
||||
SET trade_status = #{tradeStatus}, total_amount = #{totalAmount}, subject = #{subject}, body = #{body}, update_time = #{updateTime}
|
||||
WHERE out_trade_no = #{outTradeNo}
|
||||
</update>
|
||||
<select id="selectOrderById" parameterType="long" resultType="org.wfc.payment.wxpay.model.UWxPayOrderModel" resultMap="UWxPayOrderResultMap">
|
||||
SELECT * FROM u_wxpay_order WHERE id = #{id}
|
||||
</select>
|
||||
</mapper>
|
||||
@@ -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<Long> 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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
|
||||
*/
|
||||
public interface IUOrderService extends IService<UOrder> {
|
||||
|
||||
boolean saveOrder(UOrder order);
|
||||
Long saveOrder(UOrder order);
|
||||
|
||||
boolean paySuccess(Long orderId);
|
||||
}
|
||||
|
||||
@@ -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<UOrderMapper, UOrder> 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<UOrderMapper, UOrder> 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<UOrderMapper, UOrder> 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<UBillRule> billRules = billRuleMapper.selectList(Wrappers.lambdaQuery());
|
||||
billRules.stream().findFirst().ifPresent(billRule -> {
|
||||
// 测试
|
||||
if (billRule.getTraffic() == 1) {
|
||||
// 支付成功回调
|
||||
paySuccess(order.getId());
|
||||
}
|
||||
});
|
||||
|
||||
return true;
|
||||
return order.getId();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user