commit
This commit is contained in:
@@ -0,0 +1,527 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"bop_tool/app/global"
|
||||
"bop_tool/app/model"
|
||||
"encoding/csv"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
)
|
||||
|
||||
type wechatBill struct{}
|
||||
|
||||
func NewWechatBill() *wechatBill {
|
||||
return &wechatBill{}
|
||||
}
|
||||
|
||||
func (b *wechatBill) Begin() {
|
||||
data := readBillCsv("./resource/V2-20230817-1503284471.csv")
|
||||
|
||||
// fmt.Println(data)
|
||||
// _ = data
|
||||
|
||||
bills, err := buildBill(data)
|
||||
// fmt.Println(bills, err)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
transFee := int64(0)
|
||||
refundFee := int64(0)
|
||||
handFee := int64(0)
|
||||
|
||||
// currency := "CNY"
|
||||
|
||||
for _, bill := range bills {
|
||||
|
||||
totalFee, err := decimal.NewFromString(bill.Fee)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fee := totalFee.Mul(decimal.NewFromFloat(100)).IntPart()
|
||||
handFee += fee
|
||||
|
||||
// if bill.CashFeeType != currency {
|
||||
// continue
|
||||
// }
|
||||
if bill.TradeState == "SUCCESS" {
|
||||
// fmt.Println(bill)
|
||||
// verifyOrder(bill)
|
||||
|
||||
// Fee
|
||||
|
||||
totalFee, err := decimal.NewFromString(bill.TotalFee)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fee := totalFee.Mul(decimal.NewFromFloat(100)).IntPart()
|
||||
transFee += fee
|
||||
// } else if bill.TradeState == "REVOKED" {
|
||||
|
||||
} else if bill.TradeState == "REFUND" || bill.TradeState == "REVOKED" {
|
||||
// PROCESSING ???
|
||||
// verifyRefund(bill)
|
||||
totalFee, err := decimal.NewFromString(bill.RefundFee)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fee := totalFee.Mul(decimal.NewFromFloat(100)).IntPart()
|
||||
refundFee += fee
|
||||
} else {
|
||||
panic("unknown trade state")
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Println(transFee, refundFee, transFee-refundFee, transFee-refundFee-handFee)
|
||||
|
||||
}
|
||||
|
||||
func verifyOrder(bill WechatBill) error {
|
||||
fmt.Printf("begin %+v %+v\n", bill.OutTransactionId, bill.SubMchId)
|
||||
order := model.BopOrder{}
|
||||
result := global.Gorm.Where("sn = ?", bill.OutTransactionId).
|
||||
Where("channel_mch_id = ?", bill.SubMchId).
|
||||
First(&order)
|
||||
if result.RowsAffected == 0 {
|
||||
fmt.Println("order not found", bill.OutTransactionId, bill.SubMchId)
|
||||
return fmt.Errorf("order not found")
|
||||
}
|
||||
|
||||
// 验证金额
|
||||
totalFee, err := decimal.NewFromString(bill.TotalFee)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if order.TotalFee != totalFee.Mul(decimal.NewFromFloat(100)).IntPart() {
|
||||
fmt.Println("order not equal", bill.OutTransactionId, bill.SubMchId)
|
||||
return fmt.Errorf("amount not equal")
|
||||
}
|
||||
|
||||
if order.CashFeeType != bill.CashFeeType {
|
||||
fmt.Println("cash fee type not equal", bill.OutTransactionId, bill.SubMchId)
|
||||
return fmt.Errorf("cash fee type not equal")
|
||||
}
|
||||
|
||||
if order.TradeState != "SUCCESS" && order.TradeState != "REFUND" {
|
||||
fmt.Println("trade state not equal", bill.OutTransactionId, bill.SubMchId)
|
||||
return fmt.Errorf("trade state not equal")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func verifyRefund(bill WechatBill) {}
|
||||
|
||||
// type Order struct {
|
||||
// TransTime int64 `json:"trans_time"` // Transaction time
|
||||
// Appid string `json:"appid"` // Official account ID(appid)
|
||||
// MchId string `json:"mch_id"` // Vendor ID(mch_id)
|
||||
// SubMchId string `json:"sub_mch_id"` // Sub vendor ID(sub_mch_id)
|
||||
// DeviceInfo string `json:"device_info"` // Device ID(Device_info)
|
||||
// TransactionId string `json:"transaction_id"` // Wechat order number(transaction_id)
|
||||
// OutTransactionId string `json:"out_transaction_id"` // Vendor order number(out_transaction_id)
|
||||
// Openid string `json:"openid"` // User tag(openid)
|
||||
// TradeType string `json:"trade_type"` // Transaction type(trade_type)
|
||||
// TradeState string `json:"trade_state"` // Transaction status(trade_state)
|
||||
// BankType string `json:"bank_type"` // Payment bank(bank_type)
|
||||
// FeeType string `json:"fee_type"` // Currency type(fee_type)
|
||||
// TotalFee int64 `json:"total_fee"` // Total amount(total_fee)
|
||||
// CouponAmount int64 `json:"coupon_amount"` // Coupon amount
|
||||
// //RefundId string `json:"refund_id"` // Wechat refund number(refund_id)
|
||||
// //OutRefundNo string `json:"out_refund_no"` // Vendor refund number(out_refund_no)
|
||||
// //RefundFee string `json:"refund_fee"` // Refund amount(refund_fee)
|
||||
// //CouponRefundAmount string `json:"coupon_refund_amount"` // Coupon refund amount
|
||||
// //RefundType string `json:"refund_type"` // Refund type
|
||||
// //RefundStatus string `json:"refund_status"` // Refund status(refund_status)
|
||||
// ProductName string `json:"product_name"` // Product name
|
||||
// Attach string `json:"attach"` // Vendor's data package(attach)
|
||||
// Fee string `json:"fee"` // Fee
|
||||
// Rate string `json:"rate"` // Rate
|
||||
// CashFeeType string `json:"cash_fee_type"` // Payment Currency type(Cash_fee_type)
|
||||
// CashFee int64 `json:"cash_fee"` // Cash payment amount(Cash_fee)
|
||||
// SettlementCurrencyType string `json:"settlement_currency_type"` // Settlement currency type
|
||||
// SettlementCurrencyAmount int64 `json:"settlement_currency_amount"` // Settlement currency amount
|
||||
// ExchangeRate string `json:"exchange_rate"` // Exchange rate
|
||||
// //RefundExchangeRate string `json:"refund_exchange_rate"` // Refund exchange rate
|
||||
// //PayerRefundAmount string `json:"payer_refund_amount"` // Payer's Refund amount
|
||||
// //PayerRefundCurrencyType string `json:"payer_refund_currency_type"` // Payer's Refund currency type
|
||||
// //RefundCurrencyType string `json:"refund_currency_type"` // Refund currency type
|
||||
// //RefundSettlementCurrencyType string `json:"refund_settlement_currency_type"` // Refund settlement currency type
|
||||
// //RefundSettlementAmount string `json:"refund_settlement_amount"` // Refund settlement amount
|
||||
// }
|
||||
|
||||
// func buildOrder(data []WechatBill) ([]Order, error) {
|
||||
// resp := []Order{}
|
||||
// for _,b := range data {
|
||||
// o := &Order{}
|
||||
// t,err:=time.ParseInLocation("2006-01-02 15:04:05", b.TransTime, time.Local)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// o.TransTime = t.Unix()
|
||||
// o.Appid = b.Appid
|
||||
// o.MchId = b.MchId
|
||||
// o.SubMchId = b.SubMchId
|
||||
// o.DeviceInfo = b.DeviceInfo
|
||||
// o.TransactionId = b.TransactionId
|
||||
// o.OutTransactionId = b.OutTransactionId
|
||||
// o.Openid = b.Openid
|
||||
// o.TradeType = b.TradeType
|
||||
// o.TradeState = b.TradeState
|
||||
|
||||
// }
|
||||
// return resp, nil
|
||||
// }
|
||||
|
||||
func readBillCsv(path string) []map[string]string {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
reader := csv.NewReader(file)
|
||||
|
||||
header := []string{}
|
||||
data := []map[string]string{}
|
||||
|
||||
for {
|
||||
record, err := reader.Read()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// fmt.Println(record)
|
||||
|
||||
if len(header) == 0 {
|
||||
header = record
|
||||
for k, v := range header {
|
||||
// 去掉BOM头
|
||||
v = strings.Trim(v, "\xEF\xBB\xBF")
|
||||
header[k] = v
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
m := map[string]string{}
|
||||
for i, v := range header {
|
||||
m[v] = strings.Trim(record[i], "`")
|
||||
}
|
||||
data = append(data, m)
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
// func preNUm(data byte) int {
|
||||
// str := fmt.Sprintf("%b", data)
|
||||
// var i int = 0
|
||||
// for i < len(str) {
|
||||
// if str[i] != '1' {
|
||||
// break
|
||||
// }
|
||||
// i++
|
||||
// }
|
||||
// return i
|
||||
// }
|
||||
// func isUtf8(data []byte) bool {
|
||||
// for i := 0; i < len(data); {
|
||||
// if data[i]&0x80 == 0x00 {
|
||||
// // 0XXX_XXXX
|
||||
// i++
|
||||
// continue
|
||||
// } else if num := preNUm(data[i]); num > 2 {
|
||||
// // 110X_XXXX 10XX_XXXX
|
||||
// // 1110_XXXX 10XX_XXXX 10XX_XXXX
|
||||
// // 1111_0XXX 10XX_XXXX 10XX_XXXX 10XX_XXXX
|
||||
// // 1111_10XX 10XX_XXXX 10XX_XXXX 10XX_XXXX 10XX_XXXX
|
||||
// // 1111_110X 10XX_XXXX 10XX_XXXX 10XX_XXXX 10XX_XXXX 10XX_XXXX
|
||||
// // preNUm() 返回首个字节的8个bits中首个0bit前面1bit的个数,该数量也是该字符所使用的字节数
|
||||
// i++
|
||||
// for j := 0; j < num-1; j++ {
|
||||
// //判断后面的 num - 1 个字节是不是都是10开头
|
||||
// if data[i]&0xc0 != 0x80 {
|
||||
// return false
|
||||
// }
|
||||
// i++
|
||||
// }
|
||||
// } else {
|
||||
// //其他情况说明不是utf-8
|
||||
// return false
|
||||
// }
|
||||
// }
|
||||
// return true
|
||||
// }
|
||||
|
||||
// 订单
|
||||
type WechatBill struct {
|
||||
TransTime string `json:"trans_time"` // Transaction time
|
||||
Appid string `json:"appid"` // Official account ID(appid)
|
||||
MchId string `json:"mch_id"` // Vendor ID(mch_id)
|
||||
SubMchId string `json:"sub_mch_id"` // Sub vendor ID(sub_mch_id)
|
||||
DeviceInfo string `json:"device_info"` // Device ID(Device_info)
|
||||
TransactionId string `json:"transaction_id"` // Wechat order number(transaction_id)
|
||||
OutTransactionId string `json:"out_transaction_id"` // Vendor order number(out_transaction_id)
|
||||
Openid string `json:"openid"` // User tag(openid)
|
||||
TradeType string `json:"trade_type"` // Transaction type(trade_type)
|
||||
TradeState string `json:"trade_state"` // Transaction status(trade_state)
|
||||
BankType string `json:"bank_type"` // Payment bank(bank_type)
|
||||
FeeType string `json:"fee_type"` // Currency type(fee_type)
|
||||
TotalFee string `json:"total_fee"` // Total amount(total_fee)
|
||||
CouponAmount string `json:"coupon_amount"` // Coupon amount
|
||||
RefundId string `json:"refund_id"` // Wechat refund number(refund_id)
|
||||
OutRefundNo string `json:"out_refund_no"` // Vendor refund number(out_refund_no)
|
||||
RefundFee string `json:"refund_fee"` // Refund amount(refund_fee)
|
||||
CouponRefundAmount string `json:"coupon_refund_amount"` // Coupon refund amount
|
||||
RefundType string `json:"refund_type"` // Refund type
|
||||
RefundStatus string `json:"refund_status"` // Refund status(refund_status)
|
||||
ProductName string `json:"product_name"` // Product name
|
||||
Attach string `json:"attach"` // Vendor's data package(attach)
|
||||
Fee string `json:"fee"` // Fee
|
||||
Rate string `json:"rate"` // Rate
|
||||
CashFeeType string `json:"cash_fee_type"` // Payment Currency type(Cash_fee_type)
|
||||
CashFee string `json:"cash_fee"` // Cash payment amount(Cash_fee)
|
||||
SettlementCurrencyType string `json:"settlement_currency_type"` // Settlement currency type
|
||||
SettlementCurrencyAmount string `json:"settlement_currency_amount"` // Settlement currency amount
|
||||
ExchangeRate string `json:"exchange_rate"` // Exchange rate
|
||||
RefundExchangeRate string `json:"refund_exchange_rate"` // Refund exchange rate
|
||||
PayerRefundAmount string `json:"payer_refund_amount"` // Payer's Refund amount
|
||||
PayerRefundCurrencyType string `json:"payer_refund_currency_type"` // Payer's Refund currency type
|
||||
RefundCurrencyType string `json:"refund_currency_type"` // Refund currency type
|
||||
RefundSettlementCurrencyType string `json:"refund_settlement_currency_type"` // Refund settlement currency type
|
||||
RefundSettlementAmount string `json:"refund_settlement_amount"` // Refund settlement amount
|
||||
}
|
||||
|
||||
func buildBill(data []map[string]string) ([]WechatBill, error) {
|
||||
resps := []WechatBill{}
|
||||
|
||||
for _, val := range data {
|
||||
val := val
|
||||
r := WechatBill{}
|
||||
|
||||
s, ok := val["Transaction time"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Transaction time not found")
|
||||
}
|
||||
r.TransTime = s
|
||||
|
||||
s, ok = val["Official account ID(appid)"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Official account ID(appid) not found")
|
||||
}
|
||||
r.Appid = s
|
||||
|
||||
s, ok = val["Vendor ID(mch_id)"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Vendor ID(mch_id) not found")
|
||||
}
|
||||
r.MchId = s
|
||||
|
||||
s, ok = val["Sub vendor ID(sub_mch_id)"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Sub vendor ID(sub_mch_id) not found")
|
||||
}
|
||||
r.SubMchId = s
|
||||
|
||||
s, ok = val["Device ID(Device_info)"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Device ID(Device_info) not found")
|
||||
}
|
||||
r.DeviceInfo = s
|
||||
|
||||
s, ok = val["Wechat order number(transaction_id)"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Wechat order number(transaction_id) not found")
|
||||
}
|
||||
r.TransactionId = s
|
||||
|
||||
s, ok = val["Vendor order number(out_transaction_id)"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Vendor order number(out_transaction_id) not found")
|
||||
}
|
||||
|
||||
r.OutTransactionId = s
|
||||
|
||||
s, ok = val["User tag(openid)"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("User tag(openid) not found")
|
||||
}
|
||||
r.Openid = s
|
||||
|
||||
s, ok = val["Transaction type(trade_type)"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Transaction type(trade_type) not found")
|
||||
}
|
||||
r.TradeType = s
|
||||
|
||||
s, ok = val["Transaction status(trade_state)"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Transaction status(trade_state) not found")
|
||||
}
|
||||
r.TradeState = s
|
||||
|
||||
s, ok = val["Payment bank(bank_type)"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Payment bank(bank_type) not found")
|
||||
}
|
||||
r.BankType = s
|
||||
|
||||
s, ok = val["Currency type(fee_type)"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Currency type(fee_type) not found")
|
||||
}
|
||||
r.FeeType = s
|
||||
|
||||
s, ok = val["Total amount(total_fee)"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Total amount(total_fee) not found")
|
||||
}
|
||||
r.TotalFee = s
|
||||
|
||||
s, ok = val["Coupon amount"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Coupon amount not found")
|
||||
}
|
||||
r.CouponAmount = s
|
||||
|
||||
s, ok = val["Wechat refund number(refund_id)"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Wechat refund number(refund_id) not found")
|
||||
}
|
||||
r.RefundId = s
|
||||
|
||||
s, ok = val["Vendor refund number(out_refund_no)"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Vendor refund number(out_refund_no) not found")
|
||||
}
|
||||
r.OutRefundNo = s
|
||||
|
||||
s, ok = val["Refund amount(refund_fee)"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Refund amount(refund_fee) not found")
|
||||
}
|
||||
r.RefundFee = s
|
||||
|
||||
s, ok = val["Coupon refund amount"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Coupon refund amount not found")
|
||||
}
|
||||
r.CouponRefundAmount = s
|
||||
|
||||
s, ok = val["Refund type"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Refund type not found")
|
||||
}
|
||||
r.RefundType = s
|
||||
|
||||
s, ok = val["Refund status(refund_status)"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Refund status(refund_status) not found")
|
||||
}
|
||||
r.RefundStatus = s
|
||||
|
||||
s, ok = val["Product name"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Product name not found")
|
||||
}
|
||||
r.ProductName = s
|
||||
|
||||
s, ok = val["Vendor's data package(attach)"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Vendor's data package(attach) not found")
|
||||
}
|
||||
r.Attach = s
|
||||
|
||||
s, ok = val["Fee"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Fee not found")
|
||||
}
|
||||
r.Fee = s
|
||||
|
||||
s, ok = val["Rate"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Rate not found")
|
||||
}
|
||||
r.Rate = s
|
||||
|
||||
s, ok = val["Payment Currency type(Cash_fee_type)"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Payment Currency type(Cash_fee_type) not found")
|
||||
}
|
||||
r.CashFeeType = s
|
||||
|
||||
s, ok = val["Cash payment amount(Cash_fee)"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Cash payment amount(Cash_fee) not found")
|
||||
}
|
||||
r.CashFee = s
|
||||
|
||||
s, ok = val["Settlement currency type"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Settlement currency type not found")
|
||||
}
|
||||
r.SettlementCurrencyType = s
|
||||
|
||||
s, ok = val["Settlement currency amount"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Settlement currency amount not found")
|
||||
}
|
||||
r.SettlementCurrencyAmount = s
|
||||
|
||||
s, ok = val["Exchange rate"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Exchange rate not found")
|
||||
}
|
||||
r.ExchangeRate = s
|
||||
|
||||
s, ok = val["Refund exchange rate"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Refund exchange rate not found")
|
||||
}
|
||||
r.RefundExchangeRate = s
|
||||
|
||||
s, ok = val["Payer's Refund amount"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Payer's Refund amount not found")
|
||||
}
|
||||
r.PayerRefundAmount = s
|
||||
|
||||
s, ok = val["Payer's Refund currency type"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Payer's Refund currency type not found")
|
||||
}
|
||||
r.PayerRefundCurrencyType = s
|
||||
|
||||
s, ok = val["Refund currency type"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Refund currency type not found")
|
||||
}
|
||||
r.RefundCurrencyType = s
|
||||
|
||||
s, ok = val["Refund settlement currency type"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Refund settlement currency type not found")
|
||||
}
|
||||
r.RefundSettlementCurrencyType = s
|
||||
|
||||
s, ok = val["Refund settlement amount"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Refund settlement amount not found")
|
||||
}
|
||||
r.RefundSettlementAmount = s
|
||||
|
||||
resps = append(resps, r)
|
||||
|
||||
}
|
||||
|
||||
return resps, nil
|
||||
}
|
||||
Reference in New Issue
Block a user