Browse Source

发票,官网购买邮件

Bob 4 months ago
parent
commit
5d8ceda380

+ 105 - 0
pdf-office-payment/src/main/java/cn/kdan/cloud/pdf/office/payment/service/impl/PayCenterWebhookServiceImpl.java

@@ -5,14 +5,18 @@ import cn.kdan.cloud.pdf.office.api.account.feign.UserApi;
 import cn.kdan.cloud.pdf.office.api.account.feign.UserSubscriptionInfoApi;
 import cn.kdan.cloud.pdf.office.api.account.utils.SubscriptionUtil;
 import cn.kdan.cloud.pdf.office.api.account.vo.UserSubscriptionInfo;
+import cn.kdan.cloud.pdf.office.api.email.bo.EmailSendBO;
+import cn.kdan.cloud.pdf.office.api.email.feign.EmailApi;
 import cn.kdan.cloud.pdf.office.api.payment.constant.OrderConstant;
 import cn.kdan.cloud.pdf.office.api.payment.constant.SubscriptionConstant;
 import cn.kdan.cloud.pdf.office.api.payment.vo.OrdersVO;
 import cn.kdan.cloud.pdf.office.api.product.feign.ProductApi;
 import cn.kdan.cloud.pdf.office.api.product.vo.ProductVO;
+import cn.kdan.cloud.pdf.office.common.enums.EmailCodeTypeEnum;
 import cn.kdan.cloud.pdf.office.common.enums.account.AccountTypeEnum;
 import cn.kdan.cloud.pdf.office.common.enums.account.PDFOfficeUserSubscriptionStatusEnum;
 import cn.kdan.cloud.pdf.office.common.utils.CommonUtils;
+import cn.kdan.cloud.pdf.office.common.utils.MyDateUtils;
 import cn.kdan.cloud.pdf.office.common.vo.UserInfoVO;
 import cn.kdan.cloud.pdf.office.common.vo.UserSubscriptionInfoVO;
 import cn.kdan.cloud.pdf.office.common.vo.UserVO;
@@ -23,6 +27,7 @@ import cn.kdan.cloud.pdf.office.payment.service.OrderGiftService;
 import cn.kdan.cloud.pdf.office.payment.service.OrderService;
 import cn.kdan.cloud.pdf.office.payment.service.PayCenterWebhookService;
 import cn.kdan.cloud.pdf.office.payment.service.SubscriptionsService;
+import cn.kdan.cloud.pdf.office.payment.utils.TemplatesUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
@@ -32,9 +37,21 @@ import org.jetbrains.annotations.NotNull;
 import org.redisson.api.RLock;
 import org.redisson.api.RedissonClient;
 import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.util.StreamUtils;
+import org.springframework.web.client.RestTemplate;
 
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.nio.charset.StandardCharsets;
+import java.text.SimpleDateFormat;
 import java.time.ZoneId;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
@@ -64,6 +81,14 @@ public class PayCenterWebhookServiceImpl implements PayCenterWebhookService {
     private final RabbitTemplate rabbitTemplate;
 
     private final OrderGiftService orderGiftService;
+
+    private final EmailApi emailApi;
+
+    private static final RestTemplate restTemplate = new RestTemplate();
+
+    @Value("${htmlToPdfUrl:http://139.196.160.101:3060/api/get-invoice}")
+    private String htmlToPdfUrl;
+
     /**
      * 支付中台统一回调
      * @param  body  请求参数
@@ -177,10 +202,13 @@ public class PayCenterWebhookServiceImpl implements PayCenterWebhookService {
                     order.setThirdTradeNo(payId);
                     order.setStatus(OrderConstant.COMPLETED);
                     order.setPayDate(new Date());
+                    order.setInvoiceNo(MyDateUtils.getTimeStamp() + (int) ((Math.random() * 9 + 1) * 1000));
                     ordersService.updateById(order);
+                    ordersVO.setInvoiceNo(order.getInvoiceNo());
                     // 更新user_subscription_info
                     UserSubscriptionInfo userSubscriptionInfo = new UserSubscriptionInfo();
 
+                    boolean emailFlag = false;
                     // 如果是批量的购买,不需要判断用户有没有购买,直接存到订单赠送
                     if (productVO.getPlatform() == 1 && ordersVO.getPayNumber() > 1) {
                         log.info("批量购买{}个,新增订单赠送", ordersVO.getPayNumber());
@@ -241,6 +269,7 @@ public class PayCenterWebhookServiceImpl implements PayCenterWebhookService {
                                 }
                                 userApi.updateUser(userVO);
                                 userSubscriptionInfoApi.update(userSubscriptionInfo);
+                                emailFlag = true;
                             }
                         } else {
                             log.info("用户没有订阅信息,新增记录");
@@ -286,12 +315,88 @@ public class PayCenterWebhookServiceImpl implements PayCenterWebhookService {
                             }
                             userApi.updateUser(userVO);
                             userSubscriptionInfoApi.insert(userSubscriptionInfo);
+                            emailFlag = true;
                         }
                     }
                     //删除缓存中的订单
                     ordersService.deleteTheCacheInTheCacheManager(ordersVO.getUserId() + "-" + ordersVO.getProductId() + "-" + ordersVO.getPayment());
                     // 关闭用户同类型订单
                     ordersService.closeOrderByUser(ordersVO.getUserId(), productVO.getPlatform());
+                    if (emailFlag) {
+                        log.info("用户订阅或支付成功,发送订阅邮件");
+                        EmailSendBO bo = new EmailSendBO();
+                        bo.setToEmail(userInfoVO.getEmail());
+                        //设置事件
+                        if (ordersVO.getDiscountType() == 2) {
+                            bo.setUseEvent(EmailCodeTypeEnum.MEMBER_UPGRADE_SUCCESS.value());
+                        } else {
+                            bo.setUseEvent(EmailCodeTypeEnum.MEMBER_BUY_SUCCESS.value());
+                        }
+                        //设置title
+                        Map<String,String> titleMap = new HashMap<>();
+                        bo.setSendTitleContent(titleMap);
+                        //设置内容
+                        Map<String,String> contentMap = new HashMap<>();
+                        contentMap.put("@plan@", productVO.getProductName());
+                        Date date = new Date();
+                        // 创建 SimpleDateFormat 对象,指定日期格式
+                        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
+                        // 格式化当前日期
+                        String formattedDate = sdf.format(date);
+                        contentMap.put("@date@",formattedDate);
+                        String price = ObjectUtils.isNotEmpty(ordersVO.getReducedPrice())? ordersVO.getReducedPrice().toEngineeringString() : ordersVO.getPrice().toEngineeringString();
+                        contentMap.put("@payPrice@", price);
+                        contentMap.put("@renewPrice@", productVO.getPrice().toEngineeringString());
+                        bo.setSendContent(contentMap);
+                        log.info("获取发票");
+                        String invoiceHtml = null;
+                        try {
+                            invoiceHtml = new String(StreamUtils.copyToByteArray(this.getClass().getClassLoader().getResourceAsStream("templates/invoice_member.html")), StandardCharsets.UTF_8);
+                        } catch (IOException e) {
+                            log.error(e.getMessage());
+                        }
+                        Map<String, Object> map = new HashMap<>();
+                        map.put("Name", userInfoVO.getEmail());
+                        map.put("email", userInfoVO.getEmail());
+                        map.put("purchasedDate", formattedDate);
+                        map.put("orderNumber", ordersVO.getTradeNo());
+                        map.put("invoiceDate", formattedDate);
+                        map.put("invoiceNumber", ordersVO.getInvoiceNo());
+                        map.put("quantity", ordersVO.getPayNumber());
+                        map.put("unitPrice", productVO.getPrice().toEngineeringString());
+                        String discount = "0";
+                        String amount = ordersVO.getPrice().toEngineeringString();
+                        if (ordersVO.getReducedPrice() != null) {
+                            /*if (ordersVO.getPayNumber() > 0) {
+                                BigDecimal totalPrice = productVO.getPrice().multiply(BigDecimal.valueOf(ordersVO.getPayNumber()));
+                                discount = totalPrice.subtract(ordersVO.getReducedPrice()).toEngineeringString();
+                            } else {
+                                discount = productVO.getPrice().subtract(ordersVO.getReducedPrice()).toEngineeringString();
+                            }*/
+                            discount = productVO.getPrice().subtract(ordersVO.getReducedPrice()).toEngineeringString();
+                            amount = ordersVO.getReducedPrice().toEngineeringString();
+                        }
+                        map.put("discount", discount);
+                        map.put("amount", amount);
+                        map.put("total", amount);
+                        log.info("发票html内容填充map:{}", map);
+                        // 生成替换内容后的发票
+                        String htmlStr = TemplatesUtil.replaceStringUsingFreeMarker(invoiceHtml, map);
+                        HttpHeaders headers = new HttpHeaders();
+                        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+                        // 封装表单数据
+                        MultiValueMap<String, String> paramMap = new LinkedMultiValueMap<>();
+                        paramMap.add("html", htmlStr);
+                        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(paramMap, headers);
+                        // 发送POST请求,html转pdf
+                        Map postForObjectMap = restTemplate.postForObject(htmlToPdfUrl, request, Map.class);
+                        String invoiceFileUrl = postForObjectMap.get("url").toString();
+                        log.info("发票文件地址:{}", invoiceFileUrl);
+                        bo.setFileUrl(invoiceFileUrl);
+                        bo.setFileName("invoice.pdf");
+                        log.info("发送订阅邮件");
+                        emailApi.sendEmail(bo);
+                    }
                     break;
                 case "2":
                     // 支付失败,有延时队列暂不处理

+ 240 - 0
pdf-office-payment/src/main/resources/templates/invoice_member.html

@@ -0,0 +1,240 @@
+<!doctype html>
+<html>
+
+<head>
+  <title>开学季 Windows&Mac Invoice</title>
+  <meta charset='utf-8' />
+  <meta name="viewport"
+    content="width=device-width,initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
+</head>
+
+<body style="margin: 0; padding: 0;">
+  <table border="0" cellpadding="0" cellspacing="0" width="100%"
+    style="font-family: Helvetica; margin: 0; padding: 0; background: #F1F5FF;">
+    <tr>
+      <td>
+        <table align="center" border="0" cellpadding="0" cellspacing="0" width="640"
+          style="border-collapse: collapse; background-color: #fff; padding: 0 40px;">
+          <!-- 头部 -->
+          <tr>
+            <td style="padding: 0 40px;">
+              <table align="center" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse;">
+                <tr>
+                  <td style="padding-top: 40px;">
+                    <a href="https://www.pdfreaderpro.com/">
+                      <img src="https://member-system-backend.oss-us-east-1.aliyuncs.com/invoice/logo.png" alt="PDF Technologies" width="180">
+                    </a>
+                  </td>
+                </tr>
+              </table>
+            </td>
+          </tr>
+          <!-- 标题 -->
+          <tr>
+            <td style="padding: 0 40px;">
+              <table align="center" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse;">
+                <tr>
+                  <td style="padding-top: 56px;">
+                    <div style="font-weight: bold; font-size: 20px; line-height: 24px; color: #121E3F;">
+                      Invoice Information:
+                    </div>
+                  </td>
+                </tr>
+              </table>
+            </td>
+          </tr>
+          <!-- 分割线 -->
+          <tr>
+            <td style="padding: 0 40px;">
+              <table align="center" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse;">
+                <tr>
+                  <td style="padding-top: 1px; border-bottom: 2px solid #F3F3F3;">
+                    &nbsp;&nbsp;&nbsp;
+                  </td>
+                </tr>
+              </table>
+            </td>
+          </tr>
+          <!-- 主体 -->
+          <tr>
+            <td style="padding: 0 40px;">
+              <table align="center" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse;">
+                <tr>
+                  <td colspan="2" style="padding-top: 30px;">
+                    <div style="font-weight: bold;font-size: 13px; line-height: 15px; color: #121E3F;">Order
+                      Information:</div>
+                  </td>
+                  <td colspan="2" style="padding-top: 30px;">
+                    <div style="font-weight: bold;font-size: 13px; line-height: 15px; color: #121E3F;">Bill From:</div>
+                  </td>
+                </tr>
+                <tr>
+                  <td
+                    style="padding-top: 16px; padding-right: 11px; font-weight: bold; font-size: 13px; line-height: 15px; color: #121E3F;">
+                    Name</td>
+                  <td width="120"
+                    style="padding-top: 16px; padding-right: 45px; font-size: 13px; line-height: 15px; color: #121E3F; word-break:break-all;">
+                    ${Name}</td>
+                  <td
+                    style="padding-top: 16px; padding-right: 11px; font-weight: bold; font-size: 13px; line-height: 15px; color: #121E3F;">
+                    Company Name</td>
+                  <td style="padding-top: 16px; font-size: 13px; line-height: 15px; color: #121E3F;">PDF Technologies,
+                    Inc.</td>
+                </tr>
+                <tr>
+                  <td
+                    style="padding-top: 16px; padding-right: 11px; font-weight: bold; font-size: 13px; line-height: 15px; color: #121E3F;">
+                    Email</td>
+                  <td width="120"
+                    style="padding-top: 16px; padding-right: 45px; font-size: 13px; line-height: 15px; color: #121E3F; word-break:break-all;">
+                    ${email}</td>
+                  <td colspan="2"
+                    style="padding-top: 16px; font-weight: bold; font-size: 13px; line-height: 15px; color: #121E3F;">
+                    Company Address</td>
+                </tr>
+                <tr>
+                  <td
+                    style="padding-top: 16px; padding-right: 11px; font-weight: bold; font-size: 13px; line-height: 15px; color: #121E3F;">
+                    Purchase Date</td>
+                  <td
+                    style="padding-top: 16px; padding-right: 45px; font-size: 13px; line-height: 15px; color: #121E3F; word-break:break-all;">
+                    ${purchasedDate}</td>
+                  <td colspan="2" rowspan="2"
+                    style="width: 220px; padding-top: 8px; font-size: 13px; line-height: 24px; color: #121E3F;  vertical-align: top;">
+                    362 Upper Paya Lebar Road, #03-08 Da Jin Factory Building, Singapore-c</td>
+                </tr>
+                <tr>
+                  <td
+                    style="padding-top: 16px; padding-right: 11px; font-weight: bold; font-size: 13px; line-height: 15px; color: #121E3F;">
+                    Order Number</td>
+                  <td
+                    style="padding-top: 16px; padding-right: 45px; font-size: 13px; line-height: 15px; color: #121E3F; word-break:break-all;">
+                    ${orderNumber}</td>
+                </tr>
+                <tr>
+                  <td
+                    style="padding-top: 16px; padding-right: 11px; font-weight: bold; font-size: 13px; line-height: 15px; color: #121E3F;">
+                    Invoice Date</td>
+                  <td
+                    style="padding-top: 16px; padding-right: 45px; font-size: 13px; line-height: 15px; color: #121E3F;">
+                    ${invoiceDate}</td>
+                  <td
+                    style="padding-right: 20px; font-weight: bold; font-size: 13px; line-height: 15px; color: #121E3F;">
+                    Company Email</td>
+                  <td style="width: 160px; font-size: 13px; line-height: 15px; color: #121E3F;">
+                    support@pdfreaderpro.com.</td>
+                </tr>
+                <tr>
+                  <td
+                    style="padding-top: 16px; padding-right: 11px; font-weight: bold; font-size: 13px; line-height: 15px; color: #121E3F;">
+                    Invoice Number</td>
+                  <td
+                    style="padding-top: 16px; padding-right: 45px; font-size: 13px; line-height: 15px; color: #121E3F;">
+                    ${invoiceNumber}</td>
+                </tr>
+              </table>
+            </td>
+          </tr>
+          <!-- 列表 -->
+          <tr>
+            <td style="padding: 60px 40px 0px; ">
+              <table cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse;text-align: center;">
+                <tr style="background:#EFF1F5;color:#121E3F;">
+                  <td style="padding-left: 10px; text-align: left;font-size: 13px;height:40px;">Product</td>
+                  <td style="text-align: center;font-size: 13px;height:40px;">Quantity</td>
+                  <td style="text-align: center;font-size: 13px;height:40px;">Unit Price</td>
+                  <td style="text-align: center;font-size: 13px;height:40px;">Discount</td>
+                  <td style="text-align:right; padding-right: 18px; width: 84px;font-size: 13px;height:40px;">Amount
+                  </td>
+                </tr>
+
+                <tr style="height:64px;color:#333;">
+                  <td style="width:218px;height:70px;border-bottom: 2px solid #F3F3F3;" align="left">
+                    <table>
+                      <tr>
+                        <td style="padding-left: 10px;">
+                          <img src="https://member-system-backend.oss-us-east-1.aliyuncs.com/invoice/pdf.png" alt="PDF" style="width:30px; height:30px;">
+                        </td>
+                        <td
+                          style="font-weight: bold; font-size:13px; line-height: 15px; color: #121E3F; text-align:left; padding-left: 8px;">
+                          PDF Reader Pro</td>
+                      </tr>
+                    </table>
+                  </td>
+                  <td
+                    style="border-bottom: 2px solid #F3F3F3; font-size: 13px; line-height: 15px; color: #121E3F;text-align:center;">
+                    ${quantity}</td>
+                  <td
+                    style="border-bottom: 2px solid #F3F3F3; font-size: 13px; line-height: 15px; color: #121E3F;text-align:center;">
+                    USD ${unitPrice}</td>
+                  <td
+                    style="border-bottom: 2px solid #F3F3F3; font-size: 13px; line-height: 15px; color: #121E3F;text-align:center;">
+                    - USD ${discount}</td>
+                  <td
+                    style="text-align:right;padding-right: 9px;border-bottom: 2px solid #F3F3F3; font-size: 13px; line-height: 15px; color: #121E3F;">
+                    USD ${amount}
+                  </td>
+                </tr>
+              </table>
+            </td>
+          </tr>
+          <tr>
+            <td
+              style="text-align:right;padding: 16px 40px 1px 1px; font-weight: bold; font-size: 16px; line-height: 18px; color: #121E3F;">
+              Total: <span style="padding-left: 16px;">USD ${total}</span>
+            </td>
+          </tr>
+          <!-- 分割线 -->
+          <tr>
+            <td style="padding: 0 40px;">
+              <table align="center" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: collapse;">
+                <tr>
+                  <td style="padding-top: 1px; border-bottom: 2px solid #F3F3F3;">
+                    &nbsp;&nbsp;&nbsp;
+                  </td>
+                </tr>
+              </table>
+            </td>
+          </tr>
+          <tr>
+            <td style="text-align:right; padding: 16px 40px 182px; font-size: 13px; line-height: 15px; color: #8E95A6;">
+              This is computer generated invoice no signature required.
+            </td>
+          </tr>
+          <!-- 底部 -->
+          <tr>
+            <td style="padding: 0 40px; padding-bottom: 40px;">
+              <table align="center" cellpadding="0" cellspacing="0" width="100%"
+                style="border-collapse: collapse; background: #F9F9FB;">
+                <tr>
+                  <td align="center" style="padding-top: 20px;">
+                    <div style="font-size: 12px; line-height: 21px; color: #121E3F; ">
+                      Get help with subscriptions and purchases. Please contact
+                      <a href="mailto:support@pdfreaderpro.com" style="color: #3B99FC;">support@pdfreaderpro.com</a>.
+                    </div>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" style="padding-top: 16px; ">
+                    <a href="https://www.pdfreaderpro.com/">
+                      <img src="https://member-system-backend.oss-us-east-1.aliyuncs.com/invoice/logo.png" alt="PDF Technologies" width="180">
+                    </a>
+                  </td>
+                </tr>
+                <tr>
+                  <td align="center" style="padding-bottom: 20px;padding-top: 16px; ">
+                    <div style="font-size: 12px; line-height: 21px; color: #121E3F; ">
+                      © 2014-2024 PDF Technologies, Inc. All Rights Reserved.
+                    </div>
+                  </td>
+                </tr>
+              </table>
+            </td>
+          </tr>
+        </table>
+      </td>
+    </tr>
+  </table>
+</body>
+
+</html>