|
|
package bill
|
|
|
|
|
|
import (
|
|
|
"bytes"
|
|
|
"crypto/cipher"
|
|
|
"crypto/des"
|
|
|
"crypto/md5"
|
|
|
"encoding/base64"
|
|
|
"encoding/json"
|
|
|
"fmt"
|
|
|
"github.com/gin-gonic/gin"
|
|
|
"github.com/golangkit/formatime"
|
|
|
"github.com/shopspring/decimal"
|
|
|
"io/ioutil"
|
|
|
"net/http"
|
|
|
"recook/internal/back"
|
|
|
"recook/internal/dbc"
|
|
|
order1 "recook/internal/model/order"
|
|
|
"recook/tools"
|
|
|
"strconv"
|
|
|
"strings"
|
|
|
"time"
|
|
|
)
|
|
|
|
|
|
var (
|
|
|
//加密字符串
|
|
|
key64 = "LmMGStGtOpF4xNyvYt54EQ=="
|
|
|
//身份标致
|
|
|
identity = "9D9F9F13858908468CD41D4C5483AE2E00D1ACFF51C27DF1" //正式
|
|
|
//identity="2329CC5F90EDAA8208F1F3C72A0CE72A713A9D425CD50CDE"//测试
|
|
|
//开票url
|
|
|
sendUrl = "https://nnfpbox.nuonuocs.cn/shop/buyer/allow/cxfKp/cxfServerKpOrderSync.action" //测试
|
|
|
//sendUrl = "https://nnfp.jss.com.cn/shop/buyer/allow/cxfKp/cxfServerKpOrderSync.action" //正式
|
|
|
|
|
|
//根据流水查询开票状态
|
|
|
getUrl = "https://nnfpbox.nuonuocs.cn/shop/buyer/allow/ecOd/queryElectricKp.action" //测试
|
|
|
//getUrl = "https://nnfp.jss.com.cn/shop/buyer/allow/ecOd/queryElectricKp.action" //正式
|
|
|
|
|
|
)
|
|
|
|
|
|
type actionToBillPem struct {
|
|
|
GoodsDetailId []uint `json:"goodsDetailId"` //订单id,数组类型
|
|
|
Buyername string `json:"buyername"` //抬头名称
|
|
|
Taxnum string `json:"taxnum"` //购方税号
|
|
|
Address string `json:"address"` //公司地址
|
|
|
Telephone string `json:"telephone"` //公司电话
|
|
|
Phone string `json:"phone"` //购方手机
|
|
|
Email string `json:"email"` //推送邮箱
|
|
|
Account string `json:"account"` //银行账号
|
|
|
Message string `json:"message"` //备注
|
|
|
|
|
|
}
|
|
|
|
|
|
type actionToBillResult struct {
|
|
|
Status string `json:"status"`
|
|
|
Message string `json:"message"`
|
|
|
Fpqqlsh string `json:"fpqqlsh"`
|
|
|
}
|
|
|
|
|
|
func ActionToBill(c *gin.Context) {
|
|
|
|
|
|
//http.Fail(c, "开票系统正在维护中")
|
|
|
//return
|
|
|
|
|
|
var p actionToBillPem
|
|
|
err := tools.ParseParams(&p, c)
|
|
|
if err != nil {
|
|
|
back.Fail(c, err.Error())
|
|
|
return
|
|
|
}
|
|
|
|
|
|
//赋值测试效果
|
|
|
//p.Buyername = "阿库网络"
|
|
|
//p.Taxnum = "312313131"
|
|
|
//p.Address = "我的地址"
|
|
|
//p.Telephone = "0922-28228822"
|
|
|
//p.Phone = "18758321769"
|
|
|
//p.Email = "709286540@qq.com"
|
|
|
//p.Account = "42332453423142532413124343453424"
|
|
|
//p.Message = "测试备注"
|
|
|
|
|
|
//p.GoodsDetailId = []uint{865}
|
|
|
|
|
|
if len(p.GoodsDetailId) <= 0 {
|
|
|
back.Fail(c, "必须传订单明细ID")
|
|
|
return
|
|
|
}
|
|
|
type PriceAndUid struct {
|
|
|
Price decimal.Decimal `gorm:"column:price;json:"price"`
|
|
|
UserId uint `gorm:"column:user_id;json:"userId"`
|
|
|
}
|
|
|
var mypriceUid PriceAndUid
|
|
|
//从这里去开发票的金额为actual_amount+coin_amount
|
|
|
dbc.DB.Select("sum(actual_amount+coin_amount) AS price,user_id").Model(&order1.GoodsDetail{}).Where("id in (?)", p.GoodsDetailId).Scan(&mypriceUid)
|
|
|
|
|
|
//fmt.Println(mypriceUid)
|
|
|
order := " {\"identity\":\"" + identity + "\",\"order\":"
|
|
|
order = order + "{\"buyername\":\"" + p.Buyername + "\","
|
|
|
order = order + "\"" + p.Taxnum + "\":\"\","
|
|
|
order = order + "\"phone\":\"" + p.Phone + "\","
|
|
|
order = order + "\"address\":\"" + p.Address + "\","
|
|
|
order = order + "\"account\":\"" + p.Account + "\","
|
|
|
order = order + "\"telephone\":\"" + p.Telephone + "\","
|
|
|
//用第一个产品的id作为订单id
|
|
|
order = order + "\"orderno\":\"0000" + strconv.Itoa(int(p.GoodsDetailId[0])) + "\","
|
|
|
order = order + "\"invoicedate\":\"" + time.Now().Format("2006-01-02 15:04:06") + "\","
|
|
|
order = order + "\"clerk\":\"张三\"," //开票员 后期要修改
|
|
|
order = order + "\"saleaccount\":\"94170078801500000106\","
|
|
|
order = order + "\"salephone\":\"\","
|
|
|
order = order + "\"saleaddress\":\"\","
|
|
|
order = order + "\"saletaxnum\":\"91330212MA2AE2QQXR\"," //销方税号,后期要修改
|
|
|
order = order + "\"kptype\":\"1\","
|
|
|
order = order + "\"message\":\"" + p.Message + "\","
|
|
|
order = order + "\"payee\":\"\","
|
|
|
order = order + "\"checker\":\"\","
|
|
|
order = order + "\"tsfs\":\"2\"," //推送方式,手机+邮箱
|
|
|
order = order + "\"email\":\"" + p.Email + "\","
|
|
|
order = order + "\"qdbz\":\"0\","
|
|
|
order = order + "\"qdxmmc\":\"\","
|
|
|
order = order + "\"dkbz\":\"0\","
|
|
|
order = order + "\"deptid\":\"\","
|
|
|
order = order + "\"clerkid\":\"\","
|
|
|
order = order + "\"invoiceLine\":\"p\","
|
|
|
order = order + "\"cpybz\":\"\","
|
|
|
order = order + "\"detail\":[{\"goodsname\":\"瑞库客购物 \","
|
|
|
order = order + "\"num\":\"1\","
|
|
|
order = order + "\"price\":\"" + mypriceUid.Price.String() + "\","
|
|
|
order = order + "\"hsbz\":\"1\","
|
|
|
order = order + "\"taxrate\":\"0.13\","
|
|
|
order = order + "\"spec\":\"\","
|
|
|
order = order + "\"unit\":\"\","
|
|
|
order = order + "\"spbm\":\"\"," //免责协议
|
|
|
order = order + "\"zsbm\":\"\","
|
|
|
order = order + "\"fphxz\":\"0\","
|
|
|
order = order + "\"yhzcbs\":\"0\","
|
|
|
order = order + "\"zzstsgl\":\"\","
|
|
|
order = order + "\"lslbs\":\"\","
|
|
|
order = order + "\"kce\":\"\"}]}}"
|
|
|
order = encrypt(order)
|
|
|
|
|
|
resp, err := http.Post(sendUrl,
|
|
|
"application/x-www-form-urlencoded;charset=UTF-8",
|
|
|
strings.NewReader("order="+order))
|
|
|
if err != nil {
|
|
|
fmt.Println(err)
|
|
|
}
|
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
|
resp.Body.Close()
|
|
|
if err != nil {
|
|
|
fmt.Println(err)
|
|
|
}
|
|
|
|
|
|
fmt.Println(string(body))
|
|
|
var actionToBillResultData actionToBillResult
|
|
|
json.Unmarshal(body, &actionToBillResultData)
|
|
|
if actionToBillResultData.Status == "0000" {
|
|
|
//創建成功
|
|
|
//將這些訂單標記為已創建1处理中,并将流水号储存到数据中
|
|
|
dbc.DB.Model(order1.GoodsDetail{}).Where("id in (?)", p.GoodsDetailId).Updates(order1.GoodsDetail{Bill: 1, Fpqqlsh: actionToBillResultData.Fpqqlsh})
|
|
|
//这边将发票信息存储在数据库
|
|
|
billData := order1.Bill{
|
|
|
UID: mypriceUid.UserId,
|
|
|
Fpqqlsh: actionToBillResultData.Fpqqlsh,
|
|
|
Status: 20,
|
|
|
Buyername: p.Buyername,
|
|
|
Taxnum: p.Taxnum,
|
|
|
Address: p.Address,
|
|
|
Telephone: p.Telephone,
|
|
|
Phone: p.Phone,
|
|
|
Email: p.Email,
|
|
|
Account: p.Account,
|
|
|
Content: "平台消费",
|
|
|
Message: p.Message,
|
|
|
Ctime: formatime.NewSecondNow(),
|
|
|
Price: mypriceUid.Price,
|
|
|
Fail: "",
|
|
|
}
|
|
|
|
|
|
dbc.DB.Create(&billData)
|
|
|
|
|
|
back.Suc(c, "", &actionToBillResultData)
|
|
|
} else {
|
|
|
back.Fail(c, actionToBillResultData.Message)
|
|
|
}
|
|
|
return
|
|
|
|
|
|
/*
|
|
|
|
|
|
{
|
|
|
"code": "SUCCESS",
|
|
|
"data": {
|
|
|
"code": "FAIL",
|
|
|
"msg": "订单编号或流水号不能重复"
|
|
|
}
|
|
|
}
|
|
|
*/
|
|
|
|
|
|
}
|
|
|
|
|
|
type billGetData struct {
|
|
|
Result string `json:"result"`
|
|
|
List []struct {
|
|
|
TerminalNumber interface{} `json:"terminalNumber"`
|
|
|
CHjje float64 `json:"c_hjje"`
|
|
|
CAddress string `json:"c_address"`
|
|
|
CTelephone string `json:"c_telephone"`
|
|
|
CMail string `json:"c_mail"`
|
|
|
CYfpdm string `json:"c_yfpdm"`
|
|
|
CBuyername string `json:"c_buyername"`
|
|
|
CPayee string `json:"c_payee"`
|
|
|
CTaxnum string `json:"c_taxnum"`
|
|
|
CPhone string `json:"c_phone"`
|
|
|
CYfphm string `json:"c_yfphm"`
|
|
|
CSalerTel string `json:"c_salerTel"`
|
|
|
CRemark string `json:"c_remark"`
|
|
|
CipherText string `json:"cipherText"`
|
|
|
QrCode string `json:"qrCode"`
|
|
|
CInvoiceLine string `json:"c_invoice_line"`
|
|
|
CResultmsg string `json:"c_resultmsg"`
|
|
|
COfdURL string `json:"c_ofd_url"`
|
|
|
CQdbz int `json:"c_qdbz"`
|
|
|
CSalerAccount string `json:"c_salerAccount"`
|
|
|
CStatus string `json:"c_status"`
|
|
|
CKprq int64 `json:"c_kprq"`
|
|
|
CChecker string `json:"c_checker"`
|
|
|
COrderno string `json:"c_orderno"`
|
|
|
CSaleName string `json:"c_saleName"`
|
|
|
CSalerTaxNum string `json:"c_salerTaxNum"`
|
|
|
CImgUrls string `json:"c_imgUrls"`
|
|
|
MachineCode string `json:"machineCode"`
|
|
|
CJpgURL string `json:"c_jpg_url"`
|
|
|
CInvoiceid string `json:"c_invoiceid"`
|
|
|
CHjse float64 `json:"c_hjse"`
|
|
|
CClerkID string `json:"c_clerkId"`
|
|
|
CQdxmmc string `json:"c_qdxmmc"`
|
|
|
CSalerAddress string `json:"c_salerAddress"`
|
|
|
CheckCode string `json:"checkCode"`
|
|
|
CDeptID string `json:"c_deptId"`
|
|
|
CFphm string `json:"c_fphm"`
|
|
|
CClerk string `json:"c_clerk"`
|
|
|
CURL string `json:"c_url"`
|
|
|
CFpqqlsh string `json:"c_fpqqlsh"`
|
|
|
CFpdm string `json:"c_fpdm"`
|
|
|
ProductOilFlag string `json:"productOilFlag"`
|
|
|
ExtensionNumber interface{} `json:"extensionNumber"`
|
|
|
CBhsje float64 `json:"c_bhsje"`
|
|
|
CMsg string `json:"c_msg"`
|
|
|
CBankAccount string `json:"c_bankAccount"`
|
|
|
CJym string `json:"c_jym"`
|
|
|
} `json:"list"`
|
|
|
}
|
|
|
|
|
|
//这里到时候改成10分钟运行一次
|
|
|
func ActionGetBillTask() {
|
|
|
for {
|
|
|
select {
|
|
|
case <-time.After(10 * time.Minute):
|
|
|
ActionGetBill()
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
//根据流水号获取开票状态,这个用定时去跑
|
|
|
func ActionGetBill() {
|
|
|
//这里查询状态不为2的流水记录
|
|
|
var notBillData []order1.Bill
|
|
|
dbc.DB.Find(¬BillData, "status=20 OR status=21")
|
|
|
fpqqlsh := ""
|
|
|
for _, item := range notBillData {
|
|
|
if len(fpqqlsh) > 0 {
|
|
|
fpqqlsh = fpqqlsh + "," + item.Fpqqlsh
|
|
|
} else {
|
|
|
fpqqlsh = fpqqlsh + item.Fpqqlsh
|
|
|
}
|
|
|
}
|
|
|
if len(fpqqlsh) == 0 {
|
|
|
return
|
|
|
}
|
|
|
order := " {\"identity\":\"" + identity + "\","
|
|
|
order = order + "\"fpqqlsh\":[" + fpqqlsh + "]}"
|
|
|
fmt.Println(order)
|
|
|
order = encrypt(order)
|
|
|
resp, err := http.Post(getUrl,
|
|
|
"application/x-www-form-urlencoded;charset=UTF-8",
|
|
|
strings.NewReader("order="+order))
|
|
|
if err != nil {
|
|
|
fmt.Println(err)
|
|
|
}
|
|
|
|
|
|
body, err := ioutil.ReadAll(resp.Body)
|
|
|
resp.Body.Close()
|
|
|
if err != nil {
|
|
|
fmt.Println(err)
|
|
|
}
|
|
|
var billData billGetData
|
|
|
json.Unmarshal(body, &billData)
|
|
|
fmt.Println(string(body))
|
|
|
fmt.Println(billData)
|
|
|
//这里要循环返回结果并处理数据
|
|
|
for _, billDataOne := range billData.List {
|
|
|
tempStatus, _ := strconv.Atoi(billDataOne.CStatus)
|
|
|
if tempStatus != 2 {
|
|
|
dbc.DB.Model(order1.Bill{}).Where("fpqqlsh=?", billDataOne.CFpqqlsh).Update(order1.Bill{Status: tempStatus, Fail: billDataOne.CResultmsg})
|
|
|
} else {
|
|
|
dbc.DB.Model(order1.Bill{}).Where("fpqqlsh=?", billDataOne.CFpqqlsh).Update(order1.Bill{Status: tempStatus})
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
func encrypt(content string) string {
|
|
|
key, err := base64.StdEncoding.DecodeString(key64)
|
|
|
if err != nil {
|
|
|
return ""
|
|
|
}
|
|
|
sum := md5.Sum([]byte(content))
|
|
|
sourceBuf := bytes.Join([][]byte{sum[:], []byte(content)}, []byte(""))
|
|
|
p, err := DesCBCEncrypt(sourceBuf, key)
|
|
|
if err != nil {
|
|
|
return ""
|
|
|
}
|
|
|
return base64.StdEncoding.EncodeToString(p)
|
|
|
}
|
|
|
|
|
|
func DesCBCEncrypt(origData, key []byte) ([]byte, error) {
|
|
|
desKey := key[:8]
|
|
|
iv := key[8:]
|
|
|
block, err := des.NewCipher(desKey)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
origData = PKCS5Padding(origData, block.BlockSize())
|
|
|
blockMode := cipher.NewCBCEncrypter(block, iv)
|
|
|
crypted := make([]byte, len(origData))
|
|
|
blockMode.CryptBlocks(crypted, origData)
|
|
|
return crypted, nil
|
|
|
}
|
|
|
|
|
|
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
|
|
|
padding := blockSize - len(ciphertext)%blockSize
|
|
|
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
|
|
|
return append(ciphertext, padtext...)
|
|
|
}
|
|
|
|
|
|
type addLetterheadPem struct {
|
|
|
ID uint `json:"id"`
|
|
|
// UID 用户id
|
|
|
UID uint `json:"uid"`
|
|
|
// Type 1公司 2个人
|
|
|
Type uint `json:"type"`
|
|
|
// Name 名称
|
|
|
Name string `json:"name"`
|
|
|
// Taxnum 税号
|
|
|
Taxnum string `json:"taxnum"`
|
|
|
// Address 地址
|
|
|
Address string `json:"address"`
|
|
|
// Phone 电话
|
|
|
Phone string `json:"phone"`
|
|
|
// Bank 银行账号
|
|
|
Bank string `json:"bank"`
|
|
|
// Default 1默认
|
|
|
Default int `json:"default"`
|
|
|
}
|
|
|
|
|
|
//增加抬头
|
|
|
func AddLetterhead(c *gin.Context) {
|
|
|
var p addLetterheadPem
|
|
|
err := tools.ParseParams(&p, c)
|
|
|
if err != nil {
|
|
|
back.Fail(c, err.Error())
|
|
|
return
|
|
|
}
|
|
|
if p.Default == 1 {
|
|
|
dbc.DB.Table("recook_user_letterhead").Where("uid=?", p.UID).Updates(map[string]interface{}{"default": "0"})
|
|
|
}
|
|
|
|
|
|
letterheadData := order1.Letterhead{}
|
|
|
letterheadData.UID = p.UID
|
|
|
letterheadData.Type = p.Type
|
|
|
letterheadData.Name = p.Name
|
|
|
letterheadData.Taxnum = p.Taxnum
|
|
|
letterheadData.Address = p.Address
|
|
|
letterheadData.Phone = p.Phone
|
|
|
letterheadData.Bank = p.Bank
|
|
|
letterheadData.Default = p.Default
|
|
|
if p.ID > 0 {
|
|
|
dbc.DB.Table("recook_user_letterhead").Where("id=?", p.ID).Updates(map[string]interface{}{
|
|
|
"uid": letterheadData.UID,
|
|
|
"type": letterheadData.Type,
|
|
|
"name": letterheadData.Name,
|
|
|
"taxnum": letterheadData.Taxnum,
|
|
|
"address": letterheadData.Address,
|
|
|
"phone": letterheadData.Phone,
|
|
|
"bank": letterheadData.Bank,
|
|
|
"default": letterheadData.Default,
|
|
|
})
|
|
|
} else {
|
|
|
dbc.DB.Create(&letterheadData)
|
|
|
}
|
|
|
|
|
|
back.Suc(c, "", nil)
|
|
|
}
|
|
|
|
|
|
type LetterheadListPem struct {
|
|
|
Uid uint `json:"uid"`
|
|
|
}
|
|
|
type LetterheadOnePem struct {
|
|
|
ID uint `json:"id"`
|
|
|
}
|
|
|
|
|
|
//获取抬头列表
|
|
|
func LetterheadList(c *gin.Context) {
|
|
|
var p LetterheadListPem
|
|
|
err := tools.ParseParams(&p, c)
|
|
|
if err != nil {
|
|
|
//http.Fail(c, err.Error())
|
|
|
//return
|
|
|
}
|
|
|
|
|
|
var letterheadData []order1.Letterhead
|
|
|
dbc.DB.Find(&letterheadData, "uid=?", p.Uid)
|
|
|
back.Suc(c, "", &letterheadData)
|
|
|
}
|
|
|
|
|
|
//获取单个抬头
|
|
|
func LetterheadOne(c *gin.Context) {
|
|
|
var p LetterheadOnePem
|
|
|
err := tools.ParseParams(&p, c)
|
|
|
if err != nil {
|
|
|
back.Fail(c, err.Error())
|
|
|
return
|
|
|
}
|
|
|
|
|
|
var letterheadData order1.Letterhead
|
|
|
dbc.DB.Find(&letterheadData, "id=?", p.ID)
|
|
|
back.Suc(c, "", &letterheadData)
|
|
|
}
|