From 4a5d84fb2234e14360671d840356a2f3cf9f6931 Mon Sep 17 00:00:00 2001
From: laodaming <11058467+laudamine@user.noreply.gitee.com>
Date: Thu, 15 Jun 2023 19:14:19 +0800
Subject: [PATCH 1/2] fix

---
 constants/invoice_html.go                     | 238 ++++++++++++++++++
 ddl/fs_pay.sql                                |  22 ++
 model/gmodel/fs_pay_gen.go                    |  26 ++
 model/gmodel/fs_pay_logic.go                  |  11 +
 model/gmodel_gen/fs_pay_gen.go                |  26 ++
 model/gmodel_gen/fs_pay_logic.go              |   2 +
 .../handler/getorderinvoicehandler.go         |   6 +-
 .../internal/logic/getorderinvoicelogic.go    | 126 +++++++++-
 server/orders/internal/svc/servicecontext.go  |   1 +
 server/orders/internal/types/types.go         |   6 +-
 server_api/orders.api                         |   6 +-
 utils/pdf/html_to_pdf.go                      |   2 +-
 12 files changed, 458 insertions(+), 14 deletions(-)
 create mode 100644 constants/invoice_html.go
 create mode 100644 ddl/fs_pay.sql
 create mode 100644 model/gmodel/fs_pay_gen.go
 create mode 100644 model/gmodel/fs_pay_logic.go
 create mode 100644 model/gmodel_gen/fs_pay_gen.go
 create mode 100644 model/gmodel_gen/fs_pay_logic.go

diff --git a/constants/invoice_html.go b/constants/invoice_html.go
new file mode 100644
index 00000000..ae85bea5
--- /dev/null
+++ b/constants/invoice_html.go
@@ -0,0 +1,238 @@
+package constants
+
+// 主体页面
+const MAIN_INVOICE_HTML = `<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <meta charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Invoice</title>
+</head>
+
+<body style="margin: 0;">
+    <!-- header -->
+    <table border="0" align="center" cellpadding="0" cellspacing="0" width="100%"
+        style="background-color: #F8F8FA;padding: 0 5%;">
+        <tr height="30px"></tr>
+        <tr>
+            <td align="left" rowspan="9" style="vertical-align: top; width: 50%;">
+                <img style="max-height: 40px;max-width: 100%;"
+                    src="{{h5Url}}/storage/email/logo.png" alt="logo">
+            </td>
+            <td align="left" style="width: 50%;">
+                <span style="color: #212121;font-weight: bold;font-size: 42px; display: block;">Invoice</span>
+            </td>
+        </tr>
+        <tr height="30px"></tr>
+        <tr>
+            <td align="left" style="width: 50%;">
+                <span style="color: #212121;font-weight: bold;font-size: 24px; display: block;">Invoice Number:</span>
+            </td>
+        </tr>
+        <tr height="15px"></tr>
+        <tr>
+            <td align="left" style="width: 50%;">
+                <span style="color: #666666;font-weight: 400;font-size: 22px; display: block;">' . $sn . '</span>
+            </td>
+        </tr>
+        <tr height="30px"></tr>
+        <tr>
+            <td align="left" style="width: 50%;">
+                <span style="color: #212121;font-weight: bold;font-size: 24px; display: block;">Date:</span>
+            </td>
+        </tr>
+        <tr height="15px"></tr>
+        <tr>
+            <td align="left" style="width: 50%;">
+                <span style="color: #666666;font-weight: 400;font-size: 22px; display: block;">{{order_expire_time}}</span>
+            </td>
+        </tr>
+        <tr height="30px"></tr>
+    </table>
+    <!-- information -->
+    <table border="0" align="center" cellpadding="0" cellspacing="0" width="100%"
+        style="background-color: #fff;padding: 0 5%;">
+        <tr height="30px"></tr>
+        <tr>
+            <td align="left" style="width: 50%;">
+                <span style="color: #212121;font-weight: bold;font-size: 24px; display: block;">Bill To:</span>
+            </td>
+            <td align="left" style="width: 50%;">
+                <span style="color: #212121;font-weight: bold;font-size: 24px; display: block;">Bill From:</span>
+            </td>
+        </tr>
+        <tr height="15px"></tr>
+        <tr>
+            <td align="left" style="width: 50%;">
+                <span style="color: #666666;font-weight: 400;font-size: 22px; display: block; line-height: 42px;">{{name}}</span>
+            </td>
+            <td align="left" style="width: 50%;">
+                <span style="color: #666666;font-weight: 400;font-size: 22px; display: block; line-height: 42px;">Lemon
+                    Squeezy LLC</span>
+            </td>
+        </tr>
+        <tr>
+            <td align="left" style="width: 50%;">
+                <span style="color: #666666;font-weight: 400;font-size: 22px; display: block; line-height: 42px;">{{street}} {{suite}}</span>
+            </td>
+            <td align="left" style="width: 50%;">
+                <span style="color: #666666;font-weight: 400;font-size: 22px; display: block; line-height: 42px;">Lemon
+                    Squeezy LLC</span>
+            </td>
+        </tr>
+        <tr>
+            <td align="left" style="width: 50%;">
+                <span style="color: #666666;font-weight: 400;font-size: 22px; display: block; line-height: 42px;">{{city}} {{state}} {{zip_code}}</span>
+            </td>
+            <td align="left" style="width: 50%;">
+                <span style="color: #666666;font-weight: 400;font-size: 22px; display: block; line-height: 42px;">Lemon
+                    Squeezy LLC</span>
+            </td>
+        </tr>
+        <tr>
+            <td align="left" style="width: 50%;">
+                <span style="color: #666666;font-weight: 400;font-size: 22px; display: block; line-height: 42px;"> </span>
+            </td>
+            <td align="left" style="width: 50%;">
+                <span style="color: #666666;font-weight: 400;font-size: 22px; display: block; line-height: 42px;">Lemon
+                    Squeezy LLC</span>
+            </td>
+        </tr>
+        <tr height="30px"></tr>
+    </table>
+    <!-- bill -->
+    <table border="0" align="center" cellpadding="0" cellspacing="0" width="100%"
+        style="background-color: #F8F8FA;padding: 0 5%;">
+        <tr>
+            <td align="left" style="width: 50%;">
+                <span
+                    style="color: #212121;font-weight: bold;font-size: 22px; display: block; line-height: 70px;">Product
+                    Name</span>
+            </td>
+            <td align="left" style="width: 16.66%;">
+                <span style="color: #212121;font-weight: bold;font-size: 22px; display: block; line-height: 70px;">Unit
+                    Price</span>
+            </td>
+            <td align="center" style="width: 16.66%;">
+                <span
+                    style="color: #212121;font-weight: bold;font-size: 22px; display: block; line-height: 70px;">Quantity</span>
+            </td>
+            <td align="right" style="width: 16.66%;">
+                <span
+                    style="color: #212121;font-weight: bold;font-size: 22px; display: block; line-height: 70px;">Total</span>
+            </td>
+        </tr>
+    </table>
+    <table border="0" align="center" cellpadding="0" cellspacing="0" width="100%"
+        style="background-color: #fff;padding: 0 5%;">
+        <tr height="30px"></tr>
+        {{orderHTML}}
+        <tr>
+            <td align="left" colspan="2">
+                <span style="color: #666666;font-weight: 400;font-size: 22px; display: block;">Subtotal</span>
+            </td>
+            <td align="right" style="width: 16.66%;">
+                <span style="color: #666666;font-weight: 400;font-size: 22px; display: block;">${{total_amount}}</span>
+            </td>
+        </tr>
+        <tr height="15px"></tr>
+        <tr>
+            <td align="left" colspan="2">
+                <span style="color: #666666;font-weight: 400;font-size: 22px; display: block;">Tax</span>
+            </td>
+            <td align="right" style="width: 16.66%;">
+                <span style="color: #666666;font-weight: 400;font-size: 22px; display: block;">$0.00</span>
+            </td>
+        </tr>
+        <tr height="15px"></tr>
+        <tr>
+            <td align="left" colspan="2">
+                <span style="color: #666666;font-weight: 400;font-size: 22px; display: block;">Invoice Total</span>
+            </td>
+            <td align="right" style="width: 16.66%;">
+                <span style="color: #666666;font-weight: 400;font-size: 22px; display: block;">${{total_amount}}</span>
+            </td>
+        </tr>
+        <tr height="15px"></tr>
+        <tr>
+            <td align="left" colspan="2" {{first_style1}}>
+                <span style="color: #666666;font-weight: 400;font-size: 22px; display: block;">First Payment</span>
+            </td>
+            <td align="right" {{first_style2}}>
+                <span style="color: #666666;font-weight: 400;font-size: 22px; display: block;">-${{first_payment}}</span>
+            </td>
+        </tr>
+        <tr height="15px"></tr>
+        {{second_payment_html}}
+        <tr height="15px"></tr>
+        <tr>
+            <td align="left" colspan="2">
+                <span style="color: #212121;font-weight: bold;font-size: 24px; display: block;">Amount Due</span>
+            </td>
+            <td align="right" style="width: 16.66%;">
+                <span style="color: #212121;font-weight: bold;font-size: 24px; display: block;">${{amount_due}}</span>
+            </td>
+        </tr>
+        <tr height="88px"></tr>
+        <tr>
+            <td align="left" colspan="4">
+                <span style="color: #212121;font-weight: bold;font-size: 24px; display: block;">Payment Method:</span>
+            </td>
+        </tr>
+        {{pay_html}}
+        <tr height="30px"></tr>
+        <tr>
+            <td align="left" colspan="4">
+                <span style="color: #212121;font-weight: bold;font-size: 24px; display: block;">Notes:</span>
+            </td>
+        </tr>
+        <tr height="15px"></tr>
+        <tr>
+            <td align="left" colspan="4">
+                <span style="color: #666666;font-weight: 400;font-size: 22px; display: block;">Add a note...</span>
+            </td>
+        </tr>
+        <!-- <tr height="80px"></tr> -->
+    </table>
+</body>
+
+</html>`
+
+// 发票支付html模板
+const PAYMENT_HTML = `<tr height="15px"></tr>
+                        <tr>
+                            <td align="left" colspan="4">
+                                <span style="color: #666666;font-weight: 400;font-size: 22px; display: block;">${{pay_amount}} payment from {{brand}}
+                                    ····{{card_no}}</span>
+                            </td>
+                        </tr>`
+
+// 二次支付html
+const SECOND_PAYMENY_HTML = `<tr>
+		<td align="left" colspan="2"  style="padding-bottom: 20px; border-bottom: 1px solid #212121;">
+		<span style="color: #666666;font-weight: 400;font-size: 22px; display: block;">Second Payment</span>
+		</td>
+		<td align="right" style="width: 16.66%; padding-bottom: 20px; border-bottom: 1px solid #212121;">
+		<span style="color: #666666;font-weight: 400;font-size: 22px; display: block;">-${{remain_amount}}</span>
+		</td>
+		</tr>
+		<tr height="15px"></tr>`
+
+// order html
+const ORDER_HTML = `<tr>
+            <td align="left" style="width: 50%;{{style1}}" {{rowspan}}">
+                <span style="color: #212121;font-weight: bold;font-size: 22px; display: block;">{{product_title}}</span>
+            </td>
+            <td align="left" style="width: 16.66%;{{style2}}">
+                <span style="color: #666666;font-weight: 400;font-size: 22px; display: block;">${{amount}}</span>
+            </td>
+            <td align="center" style="width: 16.66%;' . $style2 . '">
+                <span style="color: #666666;font-weight: 400;font-size: 22px; display: block;">{{buy_num}}pcs</span>
+            </td>
+            <td align="right" style="width: 16.66%;' . $style2 . '">
+                <span style="color: #666666;font-weight: 400;font-size: 22px; display: block;">${{sum_amount}}</span>
+            </td>
+        </tr>
+        <tr height="15px"></tr>`
diff --git a/ddl/fs_pay.sql b/ddl/fs_pay.sql
new file mode 100644
index 00000000..d6f0212d
--- /dev/null
+++ b/ddl/fs_pay.sql
@@ -0,0 +1,22 @@
+-- fusentest.fs_pay definition
+
+CREATE TABLE `fs_pay` (
+    `id` int(11) NOT NULL AUTO_INCREMENT,
+    `user_id` int(11) NOT NULL COMMENT '用户id',
+    `order_number` varchar(255) NOT NULL COMMENT '订单编号',
+    `trade_no` varchar(255) NOT NULL DEFAULT '' COMMENT '第三方支付编号',
+    `pay_amount` int(11) NOT NULL COMMENT '支付金额 (分)',
+    `pay_status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '支付状态 0 不成功 1 成功',
+    `is_refund` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否退款 0 未退款 1退款',
+    `payment_method` tinyint(1) NOT NULL COMMENT '支付方式  1 stripe  2 paypal',
+    `pay_stage` tinyint(1) DEFAULT '0' COMMENT '支付阶段 1首付 2尾款',
+    `order_source` tinyint(1) NOT NULL DEFAULT '1' COMMENT '订单来源 1pc',
+    `pay_time` int(11) DEFAULT NULL COMMENT '支付时间',
+    `created_at` int(11) NOT NULL COMMENT '创建时间',
+    `updated_at` int(11) NOT NULL DEFAULT '0' COMMENT '更新时间',
+    `card_no` char(10) NOT NULL DEFAULT '' COMMENT '卡后4位',
+    `brand` char(20) NOT NULL DEFAULT '' COMMENT '银行品牌',
+    PRIMARY KEY (`id`) USING BTREE,
+    KEY `user_id` (`user_id`) USING BTREE,
+    KEY `trade_no` (`trade_no`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=778 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='支付记录';
\ No newline at end of file
diff --git a/model/gmodel/fs_pay_gen.go b/model/gmodel/fs_pay_gen.go
new file mode 100644
index 00000000..6a637344
--- /dev/null
+++ b/model/gmodel/fs_pay_gen.go
@@ -0,0 +1,26 @@
+package gmodel
+
+import (
+	"gorm.io/gorm"
+)
+
+type FsPay struct {
+	Id            int64   `gorm:"primary_key" json:"id"`  //
+	UserId        *int64  `gorm:"" json:"user_id"`        // 用户id
+	OrderNumber   *string `gorm:"" json:"order_number"`   // 订单编号
+	TradeNo       *string `gorm:"" json:"trade_no"`       // 第三方支付编号
+	PayAmount     *int64  `gorm:"" json:"pay_amount"`     // 支付金额 (分)
+	PayStatus     *int64  `gorm:"" json:"pay_status"`     // 支付状态 0 不成功 1 成功
+	IsRefund      *int64  `gorm:"" json:"is_refund"`      // 是否退款 0 未退款 1退款
+	PaymentMethod *int64  `gorm:"" json:"payment_method"` // 支付方式  1 stripe  2 paypal
+	PayStage      *int64  `gorm:"" json:"pay_stage"`      // 支付阶段 1首付 2尾款
+	OrderSource   *int64  `gorm:"" json:"order_source"`   // 订单来源 1pc
+	PayTime       *int64  `gorm:"" json:"pay_time"`       // 支付时间
+	CreatedAt     *int64  `gorm:"" json:"created_at"`     // 创建时间
+	UpdatedAt     *int64  `gorm:"" json:"updated_at"`     // 更新时间
+	CardNo        *string `gorm:"" json:"card_no"`        // 卡后4位
+	Brand         *string `gorm:"" json:"brand"`          // 银行品牌
+}
+type FsPayModel struct{ db *gorm.DB }
+
+func NewFsPayModel(db *gorm.DB) *FsPayModel { return &FsPayModel{db} }
diff --git a/model/gmodel/fs_pay_logic.go b/model/gmodel/fs_pay_logic.go
new file mode 100644
index 00000000..afb6f9ef
--- /dev/null
+++ b/model/gmodel/fs_pay_logic.go
@@ -0,0 +1,11 @@
+package gmodel
+
+import "context"
+
+func (p *FsPayModel) GetListByOrderNumber(ctx context.Context, sn string) (resp []FsPay, err error) {
+	err = p.db.WithContext(ctx).Model(&FsPay{}).Where("`order_number` = ? ", sn).Find(&resp).Error
+	if err != nil {
+		return nil, err
+	}
+	return resp, nil
+}
diff --git a/model/gmodel_gen/fs_pay_gen.go b/model/gmodel_gen/fs_pay_gen.go
new file mode 100644
index 00000000..9df8bffb
--- /dev/null
+++ b/model/gmodel_gen/fs_pay_gen.go
@@ -0,0 +1,26 @@
+package model
+
+import (
+	"gorm.io/gorm"
+)
+
+type FsPay struct {
+	Id            int64   `gorm:"primary_key" json:"id"`  //
+	UserId        *int64  `gorm:"" json:"user_id"`        // 用户id
+	OrderNumber   *string `gorm:"" json:"order_number"`   // 订单编号
+	TradeNo       *string `gorm:"" json:"trade_no"`       // 第三方支付编号
+	PayAmount     *int64  `gorm:"" json:"pay_amount"`     // 支付金额 (分)
+	PayStatus     *int64  `gorm:"" json:"pay_status"`     // 支付状态 0 不成功 1 成功
+	IsRefund      *int64  `gorm:"" json:"is_refund"`      // 是否退款 0 未退款 1退款
+	PaymentMethod *int64  `gorm:"" json:"payment_method"` // 支付方式  1 stripe  2 paypal
+	PayStage      *int64  `gorm:"" json:"pay_stage"`      // 支付阶段 1首付 2尾款
+	OrderSource   *int64  `gorm:"" json:"order_source"`   // 订单来源 1pc
+	PayTime       *int64  `gorm:"" json:"pay_time"`       // 支付时间
+	CreatedAt     *int64  `gorm:"" json:"created_at"`     // 创建时间
+	UpdatedAt     *int64  `gorm:"" json:"updated_at"`     // 更新时间
+	CardNo        *string `gorm:"" json:"card_no"`        // 卡后4位
+	Brand         *string `gorm:"" json:"brand"`          // 银行品牌
+}
+type FsPayModel struct{ db *gorm.DB }
+
+func NewFsPayModel(db *gorm.DB) *FsPayModel { return &FsPayModel{db} }
diff --git a/model/gmodel_gen/fs_pay_logic.go b/model/gmodel_gen/fs_pay_logic.go
new file mode 100644
index 00000000..0c571c94
--- /dev/null
+++ b/model/gmodel_gen/fs_pay_logic.go
@@ -0,0 +1,2 @@
+package model
+// TODO: 使用model的属性做你想做的
\ No newline at end of file
diff --git a/server/orders/internal/handler/getorderinvoicehandler.go b/server/orders/internal/handler/getorderinvoicehandler.go
index 03992ff7..4e2985c9 100644
--- a/server/orders/internal/handler/getorderinvoicehandler.go
+++ b/server/orders/internal/handler/getorderinvoicehandler.go
@@ -18,7 +18,7 @@ import (
 func GetOrderInvoiceHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
 	return func(w http.ResponseWriter, r *http.Request) {
 
-		var (
+		/*var (
 			// 定义错误变量
 			err error
 			// 定义用户信息变量
@@ -51,7 +51,7 @@ func GetOrderInvoiceHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
 		} else {
 			// 如果claims为nil,则认为用户身份为白板用户
 			userinfo = &auth.UserInfo{UserId: 0, GuestId: 0}
-		}
+		}*/
 
 		var req types.GetOrderInvoiceReq
 		// 如果端点有请求结构体,则使用httpx.Parse方法从HTTP请求体中解析请求数据
@@ -65,7 +65,7 @@ func GetOrderInvoiceHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
 		}
 		// 创建一个业务逻辑层实例
 		l := logic.NewGetOrderInvoiceLogic(r.Context(), svcCtx)
-		resp := l.GetOrderInvoice(&req, userinfo)
+		resp := l.GetOrderInvoice(&req, &auth.UserInfo{39, 0})
 		// 如果响应不为nil,则使用httpx.OkJsonCtx方法返回JSON响应;
 		if resp != nil {
 			httpx.OkJsonCtx(r.Context(), w, resp)
diff --git a/server/orders/internal/logic/getorderinvoicelogic.go b/server/orders/internal/logic/getorderinvoicelogic.go
index 97790923..2ab3d32b 100644
--- a/server/orders/internal/logic/getorderinvoicelogic.go
+++ b/server/orders/internal/logic/getorderinvoicelogic.go
@@ -2,9 +2,14 @@ package logic
 
 import (
 	"encoding/json"
+	"fmt"
+	"fusenapi/constants"
 	"fusenapi/model/gmodel"
 	"fusenapi/utils/auth"
 	"fusenapi/utils/basic"
+	"fusenapi/utils/pdf"
+	"strings"
+	"time"
 
 	"context"
 
@@ -34,7 +39,7 @@ func (l *GetOrderInvoiceLogic) GetOrderInvoice(req *types.GetOrderInvoiceReq, us
 	}
 	//获取用户信息
 	userModel := gmodel.NewFsUserModel(l.svcCtx.MysqlConn)
-	user, err := userModel.FindOne(l.ctx, userinfo.UserId)
+	user, err := userModel.FindUserById(l.ctx, userinfo.UserId)
 	if err != nil {
 		logx.Error(err)
 		return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get user info")
@@ -61,8 +66,121 @@ func (l *GetOrderInvoiceLogic) GetOrderInvoice(req *types.GetOrderInvoiceReq, us
 		logx.Error(err)
 		return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to parse address info")
 	}
-	if user.LastName != nil && user.FirstName != nil {
-
+	userName := ""
+	if user.LastName != nil && user.FirstName != nil && *user.LastName != "" && *user.FirstName != "" {
+		userName = *user.LastName + " " + *user.FirstName
+	} else if address.LastName != nil && address.FirstName != nil && *address.LastName != "" && *address.FirstName != "" {
+		userName = *address.LastName + " " + *address.LastName
 	}
-	return resp.SetStatus(basic.CodeOK)
+	pdfFileName := *orderInfo.Sn + "_" + userName + "_FusenPack.pdf"
+	//首款
+	firstPayment := *orderInfo.TotalAmount / 2
+	amountDue := int64(0)
+	//未完全支付
+	if *orderInfo.IsPayCompleted == 0 {
+		amountDue = *orderInfo.TotalAmount - firstPayment
+	}
+	var (
+		secondPaymentHtml string
+		firstStyle1       = `style="padding-bottom: 20px; border-bottom: 1px solid #212121;"`
+		firstStyle2       = `style="width: 16.66%; padding-bottom: 20px; border-bottom: 1px solid #212121;"`
+		payHtml           = strings.Builder{}
+		orderHTML         strings.Builder
+		totalAmount       float64
+		rowspan           = `rowspan = "12"`
+	)
+	if *orderInfo.IsPayCompleted == 1 {
+		firstStyle1 = ""
+		firstStyle2 = ""
+		rowspan = `rowspan = "14"`
+		remainAmount := float64(*orderInfo.TotalAmount - firstPayment)
+		secondPaymentHtml = strings.ReplaceAll(constants.SECOND_PAYMENY_HTML, "{{remain_amount}}", fmt.Sprintf("%.2f", remainAmount/100))
+	}
+	//获取订单详情列表
+	orderDetailModel := gmodel.NewFsOrderDetailModel(l.svcCtx.MysqlConn)
+	orderDetails, err := orderDetailModel.GetOrderDetailsByOrderId(l.ctx, orderInfo.Id)
+	if err != nil {
+		logx.Error(err)
+		return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get order details")
+	}
+	if len(orderDetails) == 0 {
+		return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "order details is empty")
+	}
+	productIds := make([]int64, 0, len(orderDetails))
+	for _, v := range orderDetails {
+		productIds = append(productIds, *v.ProductId)
+	}
+	//获取产品列表
+	productModel := gmodel.NewFsProductModel(l.svcCtx.MysqlConn)
+	productList, err := productModel.GetProductListByIds(l.ctx, productIds, "")
+	if err != nil {
+		logx.Error(err)
+		return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get product list")
+	}
+	mapProduct := make(map[int64]int)
+	for k, v := range productList {
+		mapProduct[v.Id] = k
+	}
+	payModel := gmodel.NewFsPayModel(l.svcCtx.MysqlConn)
+	payList, err := payModel.GetListByOrderNumber(l.ctx, *orderInfo.Sn)
+	if err != nil {
+		logx.Error(err)
+		return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to get payment list")
+	}
+	for _, v := range payList {
+		tem := strings.ReplaceAll(constants.PAYMENT_HTML, "{{pay_amount}}", fmt.Sprintf("%.2f", float64(*v.PayAmount)/100))
+		tem = strings.ReplaceAll(tem, "{{brand}}", *v.Brand)
+		tem = strings.ReplaceAll(tem, "{{card_no}}", *v.CardNo)
+		payHtml.WriteString(tem)
+	}
+	detailCount := len(orderDetails)
+
+	for k, v := range orderDetails {
+		amount := float64(*v.Amount)
+		sumAmount := amount * float64(*v.BuyNum)
+		totalAmount += sumAmount
+		var style1, style2 string
+		if k == (detailCount - 1) {
+			style1 = "vertical-align: top;"
+			style2 = "padding-bottom: 20px; border-bottom: 1px solid #212121;"
+		}
+		tem := strings.ReplaceAll(constants.ORDER_HTML, "{{amount}}", fmt.Sprintf("%.2f", amount/100))
+		tem = strings.ReplaceAll(tem, "{{style1}}", style1)
+		tem = strings.ReplaceAll(tem, "{{style2}}", style2)
+		tem = strings.ReplaceAll(tem, "{{rowspan}}", rowspan)
+		tem = strings.ReplaceAll(tem, "{{buy_num}}", fmt.Sprintf("%d", *v.BuyNum))
+		tem = strings.ReplaceAll(tem, "{{sum_amount}}", fmt.Sprintf("%.2f", sumAmount/100))
+		if productIndex, ok := mapProduct[*v.ProductId]; ok {
+			tem = strings.ReplaceAll(tem, "{{product_title}}", *productList[productIndex].Title)
+		} else {
+			tem = strings.ReplaceAll(tem, "{{product_title}}", "")
+		}
+		orderHTML.WriteString(tem)
+	}
+	mainHtml := strings.ReplaceAll(constants.MAIN_INVOICE_HTML, "{{pay_html}}", payHtml.String())
+	mainHtml = strings.ReplaceAll(mainHtml, "{{amount_due}}", fmt.Sprintf("%.2f", float64(amountDue)/100))
+	mainHtml = strings.ReplaceAll(mainHtml, "{{second_payment_html}}", secondPaymentHtml)
+	mainHtml = strings.ReplaceAll(mainHtml, "{{total_amount}}", fmt.Sprintf("%.2f", totalAmount/100))
+	mainHtml = strings.ReplaceAll(mainHtml, "{{first_payment}}", fmt.Sprintf("%.2f", float64(firstPayment)/100))
+	mainHtml = strings.ReplaceAll(mainHtml, "{{orderHTML}}", orderHTML.String())
+	mainHtml = strings.ReplaceAll(mainHtml, "{{city}}", *address.City)
+	mainHtml = strings.ReplaceAll(mainHtml, "{{state}}", *address.State)
+	mainHtml = strings.ReplaceAll(mainHtml, "{{zip_code}}", *address.ZipCode)
+	mainHtml = strings.ReplaceAll(mainHtml, "{{street}}", *address.Street)
+	mainHtml = strings.ReplaceAll(mainHtml, "{{suite}}", *address.Suite)
+	mainHtml = strings.ReplaceAll(mainHtml, "{{name}}", userName)
+	mainHtml = strings.ReplaceAll(mainHtml, "{{first_style1}}", firstStyle1)
+	mainHtml = strings.ReplaceAll(mainHtml, "{{first_style2}}", firstStyle2)
+	mainHtml = strings.ReplaceAll(mainHtml, "{{h5Url}}", "h5Url??????????????") // TODO ????????????
+	mainHtml = strings.ReplaceAll(mainHtml, "{{order_expire_time}}", time.Unix(*orderInfo.Ctime, req.TimeZone*60).Format("02 Jan,2006"))
+	//html内容页面转pdf的base64
+	prfBase64, err := pdf.HtmlToPdfBase64(mainHtml, 2)
+	if err != nil {
+		logx.Error(err)
+		return resp.SetStatusWithMessage(basic.CodeServiceErr, "failed to generate pdf file")
+	}
+	return resp.SetStatusWithMessage(basic.CodeOK, "success", types.GetOrderInvoiceRsp{
+		FileName: pdfFileName,
+		Pdf:      prfBase64,
+	})
 }
diff --git a/server/orders/internal/svc/servicecontext.go b/server/orders/internal/svc/servicecontext.go
index 8d5a0630..16031242 100644
--- a/server/orders/internal/svc/servicecontext.go
+++ b/server/orders/internal/svc/servicecontext.go
@@ -2,6 +2,7 @@ package svc
 
 import (
 	"errors"
+	"fmt"
 	"fusenapi/initalize"
 	"fusenapi/server/orders/internal/config"
 	"github.com/golang-jwt/jwt"
diff --git a/server/orders/internal/types/types.go b/server/orders/internal/types/types.go
index 67d5d5aa..275b6c2c 100644
--- a/server/orders/internal/types/types.go
+++ b/server/orders/internal/types/types.go
@@ -6,13 +6,13 @@ import (
 )
 
 type GetOrderInvoiceReq struct {
-	Sn       string `json:"sn"`
-	TimeZone string `json:"timeZone"`
+	Sn       string `form:"sn"`
+	TimeZone int64  `form:"timeZone"`
 }
 
 type GetOrderInvoiceRsp struct {
 	FileName string `json:"file_name"`
-	Pdf      int64  `json:"pdf"`
+	Pdf      string `json:"pdf"`
 }
 
 type Response struct {
diff --git a/server_api/orders.api b/server_api/orders.api
index 713118ac..3b4ff1c3 100644
--- a/server_api/orders.api
+++ b/server_api/orders.api
@@ -15,10 +15,10 @@ service orders {
 
 //获取订单发票
 type GetOrderInvoiceReq {
-	Sn       string `json:"sn"`
-	TimeZone string `json:"timeZone"`
+	Sn       string `form:"sn"`
+	TimeZone int64  `form:"timeZone"`
 }
 type GetOrderInvoiceRsp {
 	FileName string `json:"file_name"`
-	Pdf      int64  `json:"pdf"`
+	Pdf      string `json:"pdf"`
 }
\ No newline at end of file
diff --git a/utils/pdf/html_to_pdf.go b/utils/pdf/html_to_pdf.go
index d2c0b7a8..f2a8b15e 100644
--- a/utils/pdf/html_to_pdf.go
+++ b/utils/pdf/html_to_pdf.go
@@ -6,7 +6,7 @@ import (
 	"strings"
 )
 
-// html转 Pdf dataType = 1 为网页url dataType = 2为网页内容 outFile为空则不保存
+// html转 Pdf dataType = 1 为网页url dataType = 2为网页内容 outFile为空则不保存(使用该方法需要安装工具 sudo apt-get install wkhtmltopdf)
 func HtmlToPdfBase64(content string, dataType int, outFile ...string) (string, error) {
 	pdfg, err := wkhtmltopdf.NewPDFGenerator()
 	if err != nil {

From 0af68d5f325efebff185a4817650197a5f8da5f8 Mon Sep 17 00:00:00 2001
From: laodaming <11058467+laudamine@user.noreply.gitee.com>
Date: Thu, 15 Jun 2023 19:53:15 +0800
Subject: [PATCH 2/2] fix

---
 server/orders/internal/logic/getorderinvoicelogic.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/server/orders/internal/logic/getorderinvoicelogic.go b/server/orders/internal/logic/getorderinvoicelogic.go
index 2ab3d32b..eff54d45 100644
--- a/server/orders/internal/logic/getorderinvoicelogic.go
+++ b/server/orders/internal/logic/getorderinvoicelogic.go
@@ -171,7 +171,7 @@ func (l *GetOrderInvoiceLogic) GetOrderInvoice(req *types.GetOrderInvoiceReq, us
 	mainHtml = strings.ReplaceAll(mainHtml, "{{name}}", userName)
 	mainHtml = strings.ReplaceAll(mainHtml, "{{first_style1}}", firstStyle1)
 	mainHtml = strings.ReplaceAll(mainHtml, "{{first_style2}}", firstStyle2)
-	mainHtml = strings.ReplaceAll(mainHtml, "{{h5Url}}", "h5Url??????????????") // TODO ????????????
+	mainHtml = strings.ReplaceAll(mainHtml, "{{h5Url}}", "http://www.baidu.com") // TODO ????????????
 	mainHtml = strings.ReplaceAll(mainHtml, "{{order_expire_time}}", time.Unix(*orderInfo.Ctime, req.TimeZone*60).Format("02 Jan,2006"))
 	//html内容页面转pdf的base64
 	prfBase64, err := pdf.HtmlToPdfBase64(mainHtml, 2)