123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367 |
- package pay
- import (
- "crypto"
- "crypto/rand"
- "crypto/rsa"
- "crypto/sha256"
- "crypto/x509"
- "encoding/base64"
- "encoding/pem"
- "errors"
- "fmt"
- "hash"
- "log"
- "strings"
- "sync"
- "time"
- config "bp.jydev.jianyu360.cn/BaseService/payCenter/entity"
- // "util"
- qutil "app.yhyue.com/moapp/jybase/common"
- )
- /*
- 数据库字段 | 页面dotype
- -----------------------
- vip订阅 | subvip
- 企业商机管理 | entniche
- 历史数据 | dataexport
- 招投标课程 | course
- 数据报告 | datareport
- 中标必听课 | onlineCourse
- 大会员 | member
- AI中标预测包 | aiForecastPack
- 招标文件解读 | bidfile
- */
- var (
- vipMap = map[string]string{
- "wx_js": WX_SUBVIP_JSAPI,
- "wx_app": WX_SUBVIP_APP,
- "wx_pc": WX_SUBVIP_NATIVE,
- "ali_app": ALI_SUBVIP_APP,
- "ali_pc": ALI_SUBVIP_NATIVE,
- }
- entnicheMap = map[string]string{
- "wx_app": WX_ENTNICHE_APP,
- "wx_pc": WX_ENTNICHE_NATIVE,
- "ali_app": ALI_ENTNICHE_APP,
- "ali_pc": ALI_ENTNICHE_NATIVE,
- //"wx_js": "",
- }
- dataexportMap = map[string]string{
- "wx_js": WX_DATAEXPORT_JSAPI,
- "wx_app": WX_DATAEXPORT_APP,
- "wx_pc": WX_DATAEXPORT_NATIVE,
- "ali_app": ALI_DATAEXPORT_APP,
- "ali_pc": ALI_DATAEXPORT_NATIVE,
- }
- courseMap = map[string]string{
- "wx_js": WX_COURSE_JSAPI,
- "wx_app": WX_COURSE_APP,
- "wx_pc": WX_COURSE_NATIVE,
- "ali_app": ALI_COURSE_APP,
- "ali_pc": ALI_COURSE_NATIVE,
- }
- datareportMap = map[string]string{
- "wx_js": WX_DATAREPORT_JSAPI,
- "wx_app": WX_DATAREPORT_APP,
- "wx_pc": WX_DATAREPORT_NATIVE,
- "ali_app": ALI_DATAREPORT_APP,
- "ali_pc": ALI_DATAREPORT_NATIVE,
- }
- onlineCourseMap = map[string]string{
- "wx_js": WX_COURSEONLINE_JSAPI,
- "wx_app": WX_COURSEONLINE_APP,
- "wx_pc": WX_COURSEONLINE_NATIVE,
- "ali_app": ALI_COURSEONLINE_APP,
- "ali_pc": ALI_COURSEONLINE_NATIVE,
- }
- //大会员
- memberMap = map[string]string{
- "wx_js": WX_MEMBER_JSAPI,
- "wx_app": WX_MEMBER_APP,
- "wx_pc": WX_MEMBER_NATIVE,
- "ali_app": ALI_MEMBER_APP,
- "ali_pc": ALI_MEMBER_NATIVE,
- }
- //AI中标预测包
- aiForecastPackMap = map[string]string{
- "wx_js": WX_AIFORECASTPACK_JSAPI,
- "wx_app": WX_AIFORECASTPACK_APP,
- "wx_pc": WX_AIFORECASTPACK_NATIVE,
- "ali_app": ALI_AIFORECASTPACK_APP,
- "ali_pc": ALI_AIFORECASTPACK_NATIVE,
- }
- bifileMap = map[string]string{
- "wx_js": WX_BIDFILE_JSAPI,
- "wx_app": WX_BIDFILE_APP,
- "wx_pc": WX_BIDFILE_NATIVE,
- "ali_app": ALI_BIDFILE_APP,
- "ali_pc": ALI_BIDFILE_NATIVE,
- }
- //剑鱼币
- integralMap = map[string]string{
- "wx_js": WX_INTEGRAL_JSAPI,
- "wx_app": WX_INTEGRAL_APP,
- "wx_pc": WX_INTEGRAL_NATIVE,
- "ali_app": ALI_INTEGRAL_APP,
- "ali_pc": ALI_INTEGRAL_NATIVE,
- }
- //数据流量包
- dataPackMap = map[string]string{
- "wx_js": WX_DATAPACK_JSAIP,
- "wx_app": WX_DATAPACK_APP,
- "wx_pc": WX_DATAPACK_NATIVE,
- "ali_app": ALI_DATAPACK_APP,
- "ali_pc": ALI_DATAPACK_NATIVE,
- }
- //省份订阅包
- areaPackMap = map[string]string{
- "wx_js": WX_AREAPACK_JSAPI,
- "wx_app": WX_AREAPACK_APP,
- "wx_pc": WX_AREAPACK_NATIVE,
- "ali_app": ALI_AREAPACK_APP,
- "ali_pc": ALI_AREAPACK_NATIVE,
- }
- //附件下载包
- filePackMap = map[string]string{
- "wx_js": WX_FILEPACK_JSAPI,
- "wx_app": WX_FILEPACK_APP,
- "wx_pc": WX_FILEPACK_NATIVE,
- "ali_app": ALI_FILEPACK_APP,
- "ali_pc": ALI_FILEPACK_NATIVE,
- }
- //采购单位画像包
- buyerPortraitPackMap = map[string]string{
- "wx_js": WX_BUYERPORTRAITPACK_JSAPI,
- "wx_app": WX_BUYERPORTRAITPACK_APP,
- "wx_pc": WX_BUYERPORTRAITPACK_NATIVE,
- "ali_app": ALI_BUYERPORTRAITPACK_APP,
- "ali_pc": ALI_BUYERPORTRAITPACK_NATIVE,
- }
- PayWayAndSign = map[string]map[string]string{
- "subvip": vipMap,
- "entniche": entnicheMap,
- "dataexport": dataexportMap,
- "course": courseMap,
- "datareport": datareportMap,
- "onlineCourse": onlineCourseMap,
- "member": memberMap,
- "aiForecastPack": aiForecastPackMap,
- "bidfile": bifileMap,
- "integral": integralMap,
- "areaPack": areaPackMap,
- "filePack": filePackMap,
- "buyerPortraitPack": buyerPortraitPackMap,
- "VIP订阅": vipMap,
- "企业商机管理": entnicheMap,
- "历史数据": dataexportMap,
- "招投标课程": courseMap,
- "数据报告": datareportMap,
- "中标必听课": onlineCourseMap,
- "大会员": memberMap,
- "大会员-AI中标预测包": aiForecastPackMap,
- "招标文件解读": bifileMap,
- "大会员-招标文件解读": bifileMap,
- "剑鱼币": integralMap,
- "数据流量包": dataPackMap,
- "省份订阅包": areaPackMap,
- "附件下载包": filePackMap,
- "采购单位画像包": buyerPortraitPackMap,
- }
- varOrderCode *orderCode
- ProductType = map[string]string{
- "subvip": "VIP订阅",
- "entniche": "企业商机管理",
- "dataexport": "历史数据",
- "datareport": "数据报告",
- "onlineCourse": "中标必听课",
- "member": "大会员",
- "aiForecastPack": "大会员-AI中标预测包",
- "integral": "剑鱼币",
- "dataPack": "数据流量包",
- "areaPack": "省份订阅包",
- "filePack": "附件下载包",
- }
- )
- type orderCode struct {
- pool chan string
- all *sync.Map
- lock *sync.Mutex
- }
- func (o *orderCode) gc() {
- varOrderCode.all.Range(func(key, value interface{}) bool {
- if time.Now().Day() != value.(int) {
- varOrderCode.all.Delete(key)
- }
- return true
- })
- time.AfterFunc(24*time.Hour, o.gc)
- }
- func init() {
- varOrderCode = &orderCode{
- pool: make(chan string, 20),
- all: &sync.Map{},
- lock: &sync.Mutex{},
- }
- varOrderCode.gc()
- for i := 0; i < 10; i++ {
- go func() {
- varOrderCode.lock.Lock()
- defer varOrderCode.lock.Unlock()
- for {
- o := fmt.Sprintf("%d%s", time.Now().Unix()+900000000, qutil.GetRandom(2))
- if _, ok := varOrderCode.all.Load(o); ok {
- continue
- }
- varOrderCode.all.Store(o, time.Now().Day())
- varOrderCode.pool <- o
- }
- }()
- }
- }
- /*
- 公共创建订单
- price 价格
- productSign 产品种类标识
- ip 用户ip(仅微信支付需要)
- openid 用户openid(仅微信支付需要)
- payWay 支付方式
- */
- func CreateOrderPay(price int, productSign, ip, openid, payWay string) (tradeno, prepayid, payParam string, err error) {
- switch payWay {
- case "wx_js", "wx_app", "wx_pc": //微信公众号支付,微信app支付,微信扫码支付
- var ret *map[string]string
- tradeno, ret = WxStruct.CreatePrepayOrder(productSign, ip, openid, "", price)
- log.Println(tradeno, ret)
- if ret == nil {
- err = errors.New("创建异常")
- return
- }
- if (*ret)["status"] != "1" {
- errMsg := "创建微信订单出错"
- if (*ret)["errcodedes"] != "" {
- errMsg = (*ret)["errcodedes"]
- } else if (*ret)["errcode"] != "" {
- errMsg = (*ret)["errcode"]
- }
- err = errors.New(errMsg)
- return
- }
- prepayid = qutil.ObjToString((*ret)["prepayid"])
- if payWay == "wx_js" {
- payParam = WxStruct.GetWxjsPaySign(prepayid)
- } else if payWay == "wx_app" {
- payParam = WxStruct.GetAppWxPayStr(prepayid)
- } else if payWay == "wx_pc" {
- payParam = (*ret)["codeurl"]
- }
- case "ali_app", "ali_pc": //支付宝app支付,支付宝扫码支付
- payParam, tradeno, err = Alipay.GetOrderPayParam(qutil.Float64All(price), productSign)
- if err != nil {
- err = errors.New("创建支付宝订单出错")
- return
- }
- }
- return
- }
- //创建订单号
- func GetOrderCode(id ...string) string {
- //2020-08-01之前的规则 fmt.Sprintf("%s%s", time.Now().Format("150405"), qutil.GetRandom(6))
- return <-varOrderCode.pool
- }
- //关闭订单
- func CloseDataExportOrder(payWay, tradeno, prepayTime string) (status bool) {
- //如果订单超时 则不用关闭订单
- t, err := time.ParseInLocation("2006-01-02 15:04:05", prepayTime, time.Local)
- if err == nil {
- if t.Add(time.Hour * 2).Before(time.Now()) {
- return true
- }
- }
- //没有选择支付方式或者是测试数据
- if payWay == "" || payWay == "测试使用" || payWay == "transferAccounts" || tradeno == "" {
- return true
- }
- log.Printf("%s取消订单,订单号%s\n", payWay, tradeno)
- if strings.HasPrefix(payWay, "ali_") {
- status = Alipay.CloseOrder(tradeno)
- } else if strings.HasPrefix(payWay, "wx_") {
- status = WxStruct.CloseOrder(tradeno, payWay)
- }
- if !status {
- log.Printf("%s订单关闭失败:%s\n", payWay, tradeno)
- }
- return status
- }
- //加载秘钥
- func parsePrivateKey(key string) (*rsa.PrivateKey, error) {
- block, _ := pem.Decode([]byte(key))
- if block == nil {
- return nil, errors.New("私钥格式不正确")
- }
- if strings.ToUpper(block.Type) != "RSA PRIVATE KEY" {
- return nil, errors.New("私钥类型不正确" + block.Type)
- }
- rsaPrivateKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
- if err != nil {
- return nil, err
- }
- return rsaPrivateKey.(*rsa.PrivateKey), nil
- }
- //加载支付宝后台公钥
- func parseAliPayPublicKey(key string) (*rsa.PublicKey, error) {
- publicKeyDecoded, err := base64.StdEncoding.DecodeString(key)
- if err != nil {
- return nil, err
- }
- pub, err := x509.ParsePKIXPublicKey(publicKeyDecoded)
- if err != nil {
- return nil, err
- }
- if pub, ok := pub.(*rsa.PublicKey); ok {
- return pub, nil
- }
- return nil, errors.New("rsa.PublicKey 断言出错")
- }
- //生成加密token
- func (a *aliPayStruct) getSign(data []byte) (signature string, err error) {
- var h hash.Hash
- var hType crypto.Hash
- h = sha256.New()
- hType = crypto.SHA256
- //}
- h.Write(data)
- d := h.Sum(nil)
- bs, err := rsa.SignPKCS1v15(rand.Reader, a.PrivateKey, hType, d)
- if err != nil {
- return "", err
- }
- signature = base64.StdEncoding.EncodeToString(bs)
- return
- }
- //处理商户订单号
- func processTradeno(tradeno string) string {
- devTradenoSign := qutil.ObjToString(config.PayConf["devTradenoSign"])
- if devTradenoSign != "" {
- tradeno = devTradenoSign + tradeno
- tradeno = string([]rune(tradeno)[:len([]rune(tradeno))-len([]rune(devTradenoSign))])
- }
- return tradeno
- }
|