1、stripe
2、游客到试用用户身份转换
This commit is contained in:
@@ -50,7 +50,7 @@ public class AuthenticationFilter extends OncePerRequestFilter {
|
||||
"/api/third/party/existNoLoginRequired","/api/third/party/getRedirectUrl",
|
||||
"/api/python/flush","/api/account/healthy","/api/ali-pay/trade/notify","/api/paypal/ipn/back","/api/alipay-hk/trade/notify",
|
||||
"/api/portfolio/page", "/api/portfolio/detail", "/api/portfolio/commentPage", "/api/portfolio/viewsIncrease",
|
||||
"/api/account/designWorksRegister","/api/account/questionnaire"
|
||||
"/api/account/designWorksRegister","/api/account/questionnaire","/api/stripe/trade/notify"
|
||||
);
|
||||
|
||||
@Override
|
||||
|
||||
41
src/main/java/com/ai/da/controller/StripeController.java
Normal file
41
src/main/java/com/ai/da/controller/StripeController.java
Normal file
@@ -0,0 +1,41 @@
|
||||
package com.ai.da.controller;
|
||||
|
||||
import com.ai.da.common.response.Response;
|
||||
import com.ai.da.service.StripeService;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
@Api(tags = "Stripe模块")
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/stripe")
|
||||
public class StripeController {
|
||||
|
||||
@Resource
|
||||
private StripeService stripeService;
|
||||
|
||||
@ApiOperation("创建支付链接")
|
||||
@PostMapping("/createOrder/{amount}")
|
||||
public Response<String> pay(@PathVariable Integer amount) {
|
||||
return Response.success(stripeService.pay(amount));
|
||||
}
|
||||
|
||||
@ApiOperation("支付通知")
|
||||
@PostMapping("/trade/notify")
|
||||
public Response<String> callback(HttpServletRequest request) throws ServletException, IOException {
|
||||
Boolean result = stripeService.notify(request);
|
||||
if (result){
|
||||
return Response.success(200,"success");
|
||||
}else {
|
||||
return Response.fail(400,"failure");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,8 @@ public interface PayPalCheckoutService {
|
||||
Boolean doPost(HttpServletRequest req, HttpServletResponse resp)
|
||||
throws ServletException, IOException;
|
||||
|
||||
String getBody(HttpServletRequest request) throws IOException;
|
||||
|
||||
Order queryOrder(String orderNo) throws SerializeException;
|
||||
|
||||
Order captureOrder(String orderId) throws IOException;
|
||||
|
||||
11
src/main/java/com/ai/da/service/StripeService.java
Normal file
11
src/main/java/com/ai/da/service/StripeService.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package com.ai.da.service;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public interface StripeService {
|
||||
|
||||
String pay(Integer quantity);
|
||||
|
||||
Boolean notify(HttpServletRequest request);
|
||||
}
|
||||
@@ -508,7 +508,7 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
QueryWrapper<Account> qw = new QueryWrapper<>();
|
||||
qw.eq("BINARY user_email", accountTrialDTO.getEmail());
|
||||
List<Account> accountList = accountMapper.selectList(qw);
|
||||
if (CollectionUtil.isNotEmpty(accountList)) {
|
||||
if (CollectionUtil.isNotEmpty(accountList) && !accountList.get(0).getSystemUser().equals(0)) {
|
||||
if (accountList.get(0).getIsTrial() == 1) {
|
||||
throw new BusinessException("The email has already been registered", ResultEnum.PROMPT.getCode());
|
||||
} else {
|
||||
@@ -538,6 +538,7 @@ public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> impl
|
||||
account = CopyUtil.copyObject(accountList.get(0), Account.class);
|
||||
account.setIsTrial(1);
|
||||
account.setIsBeginner(1);
|
||||
account.setSystemUser(3);
|
||||
account.setValidStartTime(System.currentTimeMillis());
|
||||
if (link) {
|
||||
account.setValidEndTime(Instant.now().plus(14, ChronoUnit.DAYS).toEpochMilli());
|
||||
|
||||
@@ -189,7 +189,7 @@ public class PayPalCheckoutServiceImpl implements PayPalCheckoutService {
|
||||
}
|
||||
|
||||
// Simple helper method to fetch request data as a string from HttpServletRequest object.
|
||||
private static String getBody(HttpServletRequest request) throws IOException {
|
||||
public String getBody(HttpServletRequest request) throws IOException {
|
||||
String body;
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
BufferedReader bufferedReader = null;
|
||||
|
||||
285
src/main/java/com/ai/da/service/impl/StripeServiceImpl.java
Normal file
285
src/main/java/com/ai/da/service/impl/StripeServiceImpl.java
Normal file
@@ -0,0 +1,285 @@
|
||||
package com.ai.da.service.impl;
|
||||
|
||||
import com.ai.da.service.PayPalCheckoutService;
|
||||
import com.ai.da.service.StripeService;
|
||||
import com.stripe.Stripe;
|
||||
import com.stripe.exception.SignatureVerificationException;
|
||||
import com.stripe.exception.StripeException;
|
||||
import com.stripe.model.*;
|
||||
import com.stripe.model.checkout.Session;
|
||||
import com.stripe.model.issuing.Card;
|
||||
import com.stripe.net.Webhook;
|
||||
import com.stripe.param.*;
|
||||
import com.stripe.param.checkout.SessionCreateParams;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class StripeServiceImpl implements StripeService {
|
||||
|
||||
private static final String privateKey = "sk_test_51P4ZZL02n1TEydyN8qQHjOA9imsFU7Oxs2HMHGy2urHnnQgSHnZuu5vVP6pKhEACwUpsKNyrbZpdcg5TJWJLRHcY008dEO1fn2";
|
||||
// private static final String privateKey = "pk_test_51P4ZZL02n1TEydyNluht6VDxnBMoBw8S524otzlXV3CMCZI8HmkcUr3CKy8Z0eQ2WssSJ9sAaZnIQJI04fARHHJi00pcIB4sKU";
|
||||
|
||||
|
||||
|
||||
// 1、创建customer,获取customerId
|
||||
// 2、创建客户支付方式 (从前端获取)
|
||||
// 3、创建支付 paymentIntent
|
||||
// 4、确认订单
|
||||
// 5、捕获金额(执行扣款操作)
|
||||
public static String createCustomer() throws StripeException {
|
||||
Stripe.apiKey = privateKey;
|
||||
|
||||
// Customer允许重复使用
|
||||
CustomerCreateParams params =
|
||||
CustomerCreateParams.builder()
|
||||
.setName("xp")
|
||||
.setEmail("xupei3360@163.com")
|
||||
.build();
|
||||
|
||||
Customer customer = Customer.create(params);
|
||||
|
||||
return customer.getId();
|
||||
}
|
||||
|
||||
public static String createPaymentMethod(String customerId) throws StripeException {
|
||||
|
||||
Stripe.apiKey = privateKey;
|
||||
|
||||
PaymentMethodCreateParams params =
|
||||
PaymentMethodCreateParams.builder()
|
||||
.setType(PaymentMethodCreateParams.Type.CARD)
|
||||
.setCard(
|
||||
// 测试中,不建议使用卡号,会不安全的异常,必须使用token(https://docs.stripe.com/testing?testing-method=tokens#visa)
|
||||
PaymentMethodCreateParams.Token.builder().setToken("tok_visa").build()
|
||||
// PaymentMethodCreateParams.CardDetails.builder()
|
||||
// .setNumber("4242424242424242")
|
||||
// .setExpMonth(8L)
|
||||
// .setExpYear(2026L)
|
||||
// .setCvc("314")
|
||||
// .build()
|
||||
)
|
||||
.build();
|
||||
|
||||
PaymentMethod paymentMethod = PaymentMethod.create(params);
|
||||
|
||||
/*try{
|
||||
Map<String, Object> card = new HashMap<>();
|
||||
card.put("exp_month",8L);
|
||||
card.put("exp_year",2026L);
|
||||
card.put("number","4242 4242 4242 42422");
|
||||
card.put("cvc","314");
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("type", "card");
|
||||
params.put("card", card);
|
||||
PaymentMethod paymentMethod = PaymentMethod.create(params);
|
||||
Map<String, Object> params2 = new HashMap<>();
|
||||
params2.put("customer", customerId);
|
||||
paymentMethod.attach(params2);
|
||||
return paymentMethod.getId();
|
||||
}catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}*/
|
||||
// return null;
|
||||
return paymentMethod.getId();
|
||||
}
|
||||
|
||||
public static String createPaymentIntent(String paymentMethodId, String customerId) throws StripeException {
|
||||
Stripe.apiKey = privateKey;
|
||||
|
||||
Long amount = 600L;
|
||||
PaymentIntentCreateParams params =
|
||||
PaymentIntentCreateParams.builder()
|
||||
.setAmount(amount)
|
||||
// .setPaymentMethod(paymentMethodId)
|
||||
.setCustomer(customerId)
|
||||
.setCurrency("hkd")
|
||||
.setAutomaticPaymentMethods(
|
||||
PaymentIntentCreateParams.AutomaticPaymentMethods.builder()
|
||||
.setEnabled(true)
|
||||
.build()
|
||||
)
|
||||
.build();
|
||||
|
||||
PaymentIntent paymentIntent = PaymentIntent.create(params);
|
||||
return paymentIntent.getId();
|
||||
}
|
||||
|
||||
public static String confirmPaymentIntent(String clientSecret) throws StripeException {
|
||||
Stripe.apiKey = privateKey;
|
||||
|
||||
PaymentIntent resource = PaymentIntent.retrieve(clientSecret);
|
||||
|
||||
PaymentIntentConfirmParams params =
|
||||
PaymentIntentConfirmParams.builder()
|
||||
.setPaymentMethod("pm_card_visa")
|
||||
.setReturnUrl("https://www.example.com")
|
||||
.build();
|
||||
|
||||
PaymentIntent paymentIntent = resource.confirm(params);
|
||||
return paymentIntent.getId();
|
||||
}
|
||||
|
||||
public String capturePaymentIntent(String clientSecret) throws StripeException {
|
||||
|
||||
Stripe.apiKey = privateKey;
|
||||
|
||||
PaymentIntent resource = PaymentIntent.retrieve(clientSecret);
|
||||
|
||||
PaymentIntentCaptureParams params = PaymentIntentCaptureParams.builder().build();
|
||||
|
||||
PaymentIntent paymentIntent = resource.capture(params);
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws StripeException {
|
||||
// String customerId = createCustomer();
|
||||
// log.info(customerId);
|
||||
String paymentMethodId = createPaymentMethod("cus_Pvc92hQPBgLE2t");
|
||||
log.info(paymentMethodId);
|
||||
// String substring = paymentMethodId.substring(0, paymentMethodId.lastIndexOf("_"));
|
||||
// log.info(substring);
|
||||
// log.info(substring.substring(0, substring.lastIndexOf("_")));
|
||||
// String paymentIntentId = createPaymentIntent(null, "cus_Pvc92hQPBgLE2t");
|
||||
// log.info(paymentIntentId);
|
||||
|
||||
// confirmPaymentIntent("pi_3P5lr002n1TEydyN0caeqdfq");
|
||||
|
||||
}
|
||||
|
||||
public String pay(Integer quantity) {
|
||||
Stripe.apiKey = privateKey;
|
||||
try {
|
||||
//创建产品
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("name", "AiDA 积分");
|
||||
// PriceCreateParams.ProductData productData = new PriceCreateParams.ProductData.Builder().setName("AiDA 积分").build();
|
||||
Product product = Product.create(params);
|
||||
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
|
||||
String format = simpleDateFormat.format(new Date());
|
||||
|
||||
//创建价格
|
||||
Map<String, Object> priceParams = new HashMap<>();
|
||||
// BigDecimal actualAmount = createOrderEntity.getAmount().multiply(BigDecimal.valueOf(100)); //stripe的默认单位是分,即传入的amount实际上小数点会被左移两位
|
||||
BigDecimal actualAmount = new BigDecimal("600"); //stripe的默认单位是分,即传入的amount实际上小数点会被左移两位
|
||||
//给price绑定元数据并更新price用于检索
|
||||
Map<String, Object> metadata = new HashMap<>();
|
||||
metadata.put("orderId", format);
|
||||
priceParams.put("metadata", metadata); //通过订单号关联用于检索price信息(可选)
|
||||
priceParams.put("unit_amount", actualAmount.intValue());
|
||||
priceParams.put("currency", "HKD");
|
||||
priceParams.put("product", product.getId());
|
||||
// priceParams.put("product_data", product.getId());
|
||||
// PriceCreateParams priceParam = PriceCreateParams.builder().setCurrency("HKD").setProductData(productData).setUnitAmount(Long.valueOf("6")).build();
|
||||
Price price = Price.create(priceParams);
|
||||
|
||||
//创建支付信息得到url
|
||||
SessionCreateParams params3 = SessionCreateParams.builder()
|
||||
.setMode(SessionCreateParams.Mode.PAYMENT)
|
||||
.setSuccessUrl("https://www.example.com") //可自定义成功页面
|
||||
.setCancelUrl("https://www.example.com")
|
||||
.addLineItem(
|
||||
SessionCreateParams.LineItem.builder()
|
||||
.setQuantity(Long.valueOf(quantity))
|
||||
/*.setPriceData(
|
||||
new SessionCreateParams.LineItem.PriceData.Builder()
|
||||
.setCurrency("HKD")
|
||||
.setUnitAmount(Long.valueOf("600"))
|
||||
.setProductData(
|
||||
new SessionCreateParams.LineItem.PriceData.ProductData.Builder()
|
||||
.setName("AiDaA 积分")
|
||||
.build())
|
||||
.build())*/
|
||||
.setPrice(price.getId())
|
||||
.build())
|
||||
.putMetadata("orderId",format) //通过订单号关联用于检索支付信息(可选)
|
||||
.build();
|
||||
Session session = Session.create(params3);
|
||||
System.out.println("sessionId:" +session.getId());
|
||||
String sessionId = session.getId(); //退款方式1:拿到sessionId入库,退款的时候根据这个id找到PaymentIntent的id然后发起退款
|
||||
return session.getUrl();
|
||||
}catch (Exception e){
|
||||
log.error("创建支付会话出现异常:",e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@Resource
|
||||
private PayPalCheckoutService payPalCheckoutService;
|
||||
|
||||
@Override
|
||||
public Boolean notify(HttpServletRequest request){
|
||||
log.info("stripe异步通知进行中");
|
||||
String payload = null;
|
||||
String sigHeader= null;
|
||||
// String endpointSecret = "whsec_xxxgx92OjXdBf1lc2c";//webhook秘钥签名
|
||||
String endpointSecret = "whsec_e0dBiJngx6qqgJj6yPyJ2A9ouh1Cjv5w";//webhook秘钥签名
|
||||
try {
|
||||
sigHeader = request.getHeader("Stripe-Signature");
|
||||
payload = payPalCheckoutService.getBody(request);
|
||||
} catch (Exception e) {
|
||||
log.info("stripe 支付回调参数解析异常:errorMsg {}", e.getMessage());
|
||||
log.info("request sigHeader = {}", sigHeader);
|
||||
log.info("request body = {}", payload);
|
||||
e.printStackTrace();
|
||||
return Boolean.FALSE;
|
||||
// response.setStatus(400);
|
||||
}
|
||||
|
||||
Event event = null;
|
||||
try {
|
||||
assert sigHeader != null;
|
||||
event = Webhook.constructEvent(payload, sigHeader, endpointSecret);
|
||||
} catch (SignatureVerificationException e) {
|
||||
log.info("stripe 验签,获取事件异常, errorMsg=" + e.getMessage());
|
||||
log.info("request sigHeader = {}", sigHeader);
|
||||
log.info("request body = {}", payload);
|
||||
e.printStackTrace();
|
||||
return Boolean.FALSE;
|
||||
// response.setStatus(400);
|
||||
}
|
||||
|
||||
|
||||
//获取自定义参数
|
||||
// Deserialize the nested object inside the event
|
||||
assert event != null;
|
||||
EventDataObjectDeserializer dataObjectDeserializer = event.getDataObjectDeserializer();
|
||||
StripeObject stripeObject = null;
|
||||
if (dataObjectDeserializer.getObject().isPresent()) {
|
||||
stripeObject = dataObjectDeserializer.getObject().get();
|
||||
|
||||
} else {
|
||||
log.info("stripe 验签失败!");
|
||||
log.info("request sigHeader = {}", sigHeader);
|
||||
log.info("request body = {}", payload);
|
||||
return Boolean.FALSE;
|
||||
// response.setStatus(400);
|
||||
}
|
||||
|
||||
if (event.getType().equals("checkout.session.completed")){
|
||||
|
||||
}
|
||||
log.info("stripe验签成功");
|
||||
return Boolean.TRUE;
|
||||
// response.setStatus(200);
|
||||
|
||||
|
||||
// 1、验签
|
||||
|
||||
// 2、处理订单
|
||||
// 2.1 更新订单状态
|
||||
// 2.2 添加积分
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user