支付模块
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

409 lines
13 KiB

  1. package local_wxpay
  2. import (
  3. zhios_pay_utils "code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git/utils"
  4. "code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git/utils/logx"
  5. "code.fnuoos.com/go_rely_warehouse/zyos_go_pay.git/utils/qrcode"
  6. "fmt"
  7. "github.com/iGoogle-ink/gopay"
  8. "github.com/iGoogle-ink/gopay/pkg/util"
  9. "github.com/iGoogle-ink/gopay/pkg/xlog"
  10. "github.com/iGoogle-ink/gopay/wechat"
  11. v3 "github.com/iGoogle-ink/gopay/wechat/v3"
  12. "strconv"
  13. "strings"
  14. "time"
  15. )
  16. func NewClient(appId, mchId, apiKey string, isProd bool) *wechat.Client {
  17. // 初始化微信客户端
  18. // appId:应用ID
  19. // mchId:商户ID
  20. // apiKey:API秘钥值
  21. // isProd:是否是正式环境
  22. client := wechat.NewClient(appId, mchId, apiKey, isProd)
  23. // 打开Debug开关,输出请求日志,默认关闭
  24. client.DebugSwitch = gopay.DebugOn
  25. // 设置国家:不设置默认 中国国内
  26. // wechat.China:中国国内
  27. // wechat.China2:中国国内备用
  28. // wechat.SoutheastAsia:东南亚
  29. // wechat.Other:其他国家
  30. client.SetCountry(wechat.China)
  31. // 添加微信证书 Path 路径
  32. // certFilePath:apiclient_cert.pem 路径
  33. // keyFilePath:apiclient_key.pem 路径
  34. // pkcs12FilePath:apiclient_cert.p12 路径
  35. // 返回err
  36. //client.AddCertFilePath()
  37. // 添加微信证书内容 Content
  38. // certFileContent:apiclient_cert.pem 内容
  39. // keyFileContent:apiclient_key.pem 内容
  40. // pkcs12FileContent:apiclient_cert.p12 内容
  41. // 返回err
  42. //client.AddCertFileContent()
  43. return client
  44. }
  45. func TradeAppRefund(client *wechat.Client, subject, transactionId, outRefundNo, totalFee, amount, p12Path, notifyUrl string) (*wechat.RefundResponse, gopay.BodyMap, error) {
  46. // 初始化 BodyMap
  47. bm := make(gopay.BodyMap)
  48. bm.Set("transaction_id", transactionId).
  49. Set("nonce_str", util.GetRandomString(32)).
  50. Set("sign_type", wechat.SignType_MD5).
  51. Set("out_refund_no", outRefundNo).
  52. Set("total_fee", totalFee).
  53. Set("refund_fee", amount).
  54. Set("refund_desc", subject).
  55. Set("notify_url", notifyUrl)
  56. wxRsp, resBm, err := client.Refund(bm, nil, nil, p12Path)
  57. fmt.Println(wxRsp)
  58. fmt.Println(resBm)
  59. if err != nil {
  60. xlog.Error(err)
  61. fmt.Println(err)
  62. return wxRsp, resBm, err
  63. }
  64. return wxRsp, resBm, nil
  65. }
  66. func TradeAppRefundQuery(client *wechat.Client, transactionId string) (*wechat.QueryRefundResponse, gopay.BodyMap, error) {
  67. // 初始化 BodyMap
  68. bm := make(gopay.BodyMap)
  69. bm.Set("transaction_id", transactionId).
  70. Set("nonce_str", util.GetRandomString(32)).
  71. Set("sign_type", wechat.SignType_MD5)
  72. wxRsp, resBm, err := client.QueryRefund(bm)
  73. fmt.Println(wxRsp)
  74. fmt.Println(resBm)
  75. if err != nil {
  76. xlog.Error(err)
  77. fmt.Println(err)
  78. return wxRsp, resBm, err
  79. }
  80. return wxRsp, resBm, nil
  81. }
  82. func TradeShowQuery(client *wechat.Client, transactionId string) (*wechat.QueryOrderResponse, gopay.BodyMap, error) {
  83. // 初始化 BodyMap
  84. bm := make(gopay.BodyMap)
  85. bm.Set("transaction_id", transactionId).
  86. Set("nonce_str", util.GetRandomString(32)).
  87. Set("sign_type", wechat.SignType_MD5)
  88. wxRsp, resBm, err := client.QueryOrder(bm)
  89. fmt.Println(wxRsp)
  90. fmt.Println(resBm)
  91. if err != nil {
  92. xlog.Error(err)
  93. fmt.Println(err)
  94. return wxRsp, resBm, err
  95. }
  96. return wxRsp, resBm, nil
  97. }
  98. func TradeShowRefundQuery(client *wechat.Client, transactionId string) (*wechat.QueryRefundResponse, gopay.BodyMap, error) {
  99. // 初始化 BodyMap
  100. bm := make(gopay.BodyMap)
  101. bm.Set("transaction_id", transactionId).
  102. Set("nonce_str", util.GetRandomString(32)).
  103. Set("sign_type", wechat.SignType_MD5)
  104. wxRsp, resBm, err := client.QueryRefund(bm)
  105. fmt.Println(wxRsp)
  106. fmt.Println(resBm)
  107. if err != nil {
  108. xlog.Error(err)
  109. fmt.Println(err)
  110. return wxRsp, resBm, err
  111. }
  112. return wxRsp, resBm, nil
  113. }
  114. // TradeAppPay is 微信APP支付
  115. func TradeAppPay(client *wechat.Client, subject, orderID, amount, notifyUrl string) (map[string]string, error) {
  116. // 初始化 BodyMap
  117. bm := make(gopay.BodyMap)
  118. bm.Set("nonce_str", util.GetRandomString(32)).
  119. Set("body", subject).
  120. Set("out_trade_no", orderID).
  121. Set("total_fee", amount).
  122. Set("spbill_create_ip", "127.0.0.1").
  123. Set("notify_url", notifyUrl).
  124. Set("trade_type", wechat.TradeType_App).
  125. Set("sign_type", wechat.SignType_MD5)
  126. /*.Set("openid", "o0Df70H2Q0fY8JXh1aFPIRyOBgu8")*/
  127. // 预下单
  128. wxRsp, err := client.UnifiedOrder(bm)
  129. if err != nil {
  130. _ = zhios_pay_logx.Warn(err)
  131. return nil, err
  132. }
  133. _, err = wechat.VerifySign(client.ApiKey, wechat.SignType_MD5, wxRsp)
  134. if err != nil {
  135. _ = zhios_pay_logx.Warn(err)
  136. return nil, err
  137. }
  138. //if !ok {
  139. // return nil, errors.New("验签失败")
  140. //}
  141. timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
  142. paySign := wechat.GetAppPaySign(client.AppId, client.MchId, wxRsp.NonceStr, wxRsp.PrepayId, wechat.SignType_MD5, timeStamp, client.ApiKey)
  143. res := map[string]string{
  144. "appid": client.AppId,
  145. "partnerid": client.MchId,
  146. "prepayid": wxRsp.PrepayId,
  147. "sign": paySign,
  148. "package": "Sign=WXPay",
  149. "noncestr": wxRsp.NonceStr,
  150. "timestamp": timeStamp,
  151. }
  152. return res, nil
  153. }
  154. // TradeAppPay is 微信H5支付
  155. func TradeH5Pay(client *wechat.Client, subject, orderID, amount, notifyUrl string) (map[string]string, error) {
  156. // 初始化 BodyMap
  157. bm := make(gopay.BodyMap)
  158. bm.Set("nonce_str", util.GetRandomString(32)).
  159. Set("body", subject).
  160. Set("out_trade_no", orderID).
  161. Set("total_fee", amount).
  162. Set("spbill_create_ip", "121.196.29.49").
  163. Set("notify_url", notifyUrl).
  164. Set("trade_type", wechat.TradeType_H5).
  165. Set("sign_type", wechat.SignType_MD5).
  166. SetBodyMap("scene_info", func(bm gopay.BodyMap) {
  167. bm.SetBodyMap("h5_info", func(bm gopay.BodyMap) {
  168. bm.Set("type", "Wap")
  169. bm.Set("wap_url", "https://www.fumm.cc")
  170. bm.Set("wap_name", "zyos")
  171. })
  172. })
  173. /*.Set("openid", "o0Df70H2Q0fY8JXh1aFPIRyOBgu8")*/
  174. // 预下单
  175. wxRsp, err := client.UnifiedOrder(bm)
  176. if err != nil {
  177. _ = zhios_pay_logx.Warn(err)
  178. return nil, err
  179. }
  180. _, err = wechat.VerifySign(client.ApiKey, wechat.SignType_MD5, wxRsp)
  181. if err != nil {
  182. _ = zhios_pay_logx.Warn(err)
  183. return nil, err
  184. }
  185. timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
  186. packages := "prepay_id=" + wxRsp.PrepayId
  187. paySign := wechat.GetH5PaySign(client.AppId, wxRsp.NonceStr, packages, wechat.SignType_MD5, timeStamp, client.ApiKey)
  188. fmt.Println("paySign===", paySign)
  189. r := map[string]string{
  190. "redirect_url": wxRsp.MwebUrl,
  191. }
  192. return r, nil
  193. }
  194. func TradePcPay(client *wechat.Client, subject, orderID, amount, notifyUrl, productId string) (map[string]string, error) {
  195. // 初始化 BodyMap
  196. bm := make(gopay.BodyMap)
  197. bm.Set("nonce_str", util.GetRandomString(32)).
  198. Set("body", subject).
  199. Set("out_trade_no", orderID).
  200. Set("total_fee", amount).
  201. Set("spbill_create_ip", "121.196.29.49").
  202. Set("notify_url", notifyUrl).
  203. Set("product_id", productId).
  204. Set("trade_type", wechat.TradeType_Native).
  205. Set("sign_type", wechat.SignType_MD5)
  206. // 预下单
  207. wxRsp, err := client.UnifiedOrder(bm)
  208. if err != nil {
  209. _ = zhios_pay_logx.Warn(err)
  210. return nil, err
  211. }
  212. QRcode := ""
  213. if wxRsp.CodeUrl != "" {
  214. QRcode = qrcode.GetPNGBase64(wxRsp.CodeUrl)
  215. }
  216. QRcode = strings.ReplaceAll(QRcode, "\u0000", "")
  217. r := map[string]string{
  218. "payQrcode": QRcode,
  219. }
  220. return r, nil
  221. }
  222. // TradeMiniProgPay is 微信小程序支付 ☑️
  223. func TradeMiniProgPay(client *wechat.Client, subject, orderID, amount, notifyUrl, openid string) (map[string]string, error) {
  224. if len(subject) > 127 {
  225. tmpSubject := []rune(subject)
  226. subject = string(tmpSubject[0:44])
  227. }
  228. // 初始化 BodyMap
  229. bm := make(gopay.BodyMap)
  230. bm.Set("nonce_str", util.GetRandomString(32)).
  231. Set("body", subject).
  232. Set("openid", openid).
  233. Set("out_trade_no", orderID).
  234. Set("total_fee", amount).
  235. Set("spbill_create_ip", "127.0.0.1").
  236. Set("notify_url", notifyUrl).
  237. Set("trade_type", wechat.TradeType_Mini).
  238. Set("sign_type", wechat.SignType_MD5)
  239. // 预下单
  240. wxRsp, err := client.UnifiedOrder(bm)
  241. if err != nil {
  242. _ = zhios_pay_logx.Warn(err)
  243. return nil, err
  244. }
  245. fmt.Println(wxRsp)
  246. timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
  247. packages := "prepay_id=" + wxRsp.PrepayId
  248. paySign := wechat.GetMiniPaySign(client.AppId, wxRsp.NonceStr, packages, wechat.SignType_MD5, timeStamp, client.ApiKey)
  249. res := map[string]string{
  250. "appId": client.AppId,
  251. "paySign": paySign,
  252. "signType": wechat.SignType_MD5,
  253. "package": packages,
  254. "nonceStr": wxRsp.NonceStr,
  255. "timeStamp": timeStamp,
  256. }
  257. return res, nil
  258. }
  259. // TradeAppPayV3 is 微信APP支付v3
  260. func TradeAppPayV3(client *v3.ClientV3, subject, orderID, amount, notifyUrl string) (map[string]string, error) {
  261. // 初始化 BodyMap
  262. amountNew := zhios_pay_utils.AnyToFloat64(amount) * 100
  263. bm := make(gopay.BodyMap)
  264. bm.Set("nonce_str", util.GetRandomString(32)).
  265. Set("body", subject).
  266. Set("out_trade_no", orderID).
  267. Set("total_fee", amountNew).
  268. Set("spbill_create_ip", "127.0.0.1").
  269. Set("notify_url", notifyUrl).
  270. Set("trade_type", wechat.TradeType_App).
  271. Set("sign_type", wechat.SignType_MD5)
  272. /*.Set("openid", "o0Df70H2Q0fY8JXh1aFPIRyOBgu8")*/
  273. //// 预下单
  274. //wxRsp, err := v3.UnifiedOrder(bm)
  275. //if err != nil {
  276. // _ = zhios_pay_logx.Warn(err)
  277. // return nil, err
  278. //}
  279. //_, err = wechat.VerifySign(client.ApiKey, wechat.SignType_MD5, wxRsp)
  280. //if err != nil {
  281. // _ = zhios_pay_logx.Warn(err)
  282. // return nil, err
  283. //}
  284. ////if !ok {
  285. //// return nil, errors.New("验签失败")
  286. ////}
  287. //timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
  288. //paySign := wechat.GetAppPaySign(client.AppId, client.MchId, wxRsp.NonceStr, wxRsp.PrepayId, wechat.SignType_MD5, timeStamp, client.ApiKey)
  289. //res := map[string]string{
  290. // "appid": client.AppId,
  291. // "partnerid": client.MchId,
  292. // "prepayid": wxRsp.PrepayId,
  293. // "sign": paySign,
  294. // "package": "Sign=WXPay",
  295. // "noncestr": wxRsp.NonceStr,
  296. // "timestamp": timeStamp,
  297. //}
  298. //return res, nil
  299. return nil, nil
  300. }
  301. //// TradeJSAPIPay is 微信JSAPI支付
  302. func TradeJSAPIPay(client *wechat.Client, subject, orderID, amount, notifyUrl, openid string) (map[string]string, error) {
  303. // 初始化 BodyMap
  304. bm := make(gopay.BodyMap)
  305. bm.Set("nonce_str", util.GetRandomString(32)).
  306. Set("body", subject).
  307. Set("out_trade_no", orderID).
  308. Set("total_fee", amount).
  309. Set("spbill_create_ip", "121.196.29.49").
  310. Set("notify_url", notifyUrl).
  311. Set("trade_type", wechat.TradeType_JsApi).
  312. Set("sign_type", wechat.SignType_MD5).
  313. Set("openid", openid).
  314. SetBodyMap("scene_info", func(bm gopay.BodyMap) {
  315. bm.SetBodyMap("h5_info", func(bm gopay.BodyMap) {
  316. bm.Set("type", "Wap")
  317. bm.Set("wap_url", "https://www.fumm.cc")
  318. bm.Set("wap_name", "zyos")
  319. })
  320. })
  321. // 预下单
  322. wxRsp, err := client.UnifiedOrder(bm)
  323. if err != nil {
  324. _ = zhios_pay_logx.Warn(err)
  325. return nil, err
  326. }
  327. _, err = wechat.VerifySign(client.ApiKey, wechat.SignType_MD5, wxRsp)
  328. if err != nil {
  329. _ = zhios_pay_logx.Warn(err)
  330. return nil, err
  331. }
  332. //if !ok {
  333. // return nil, errors.New("验签失败")
  334. //}
  335. timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
  336. //paySign := wechat.GetAppPaySign(client.AppId, client.MchId, wxRsp.NonceStr, wxRsp.PrepayId, wechat.SignType_MD5, timeStamp, client.ApiKey)
  337. packages := "prepay_id=" + wxRsp.PrepayId
  338. paySign := wechat.GetJsapiPaySign(client.AppId, wxRsp.NonceStr, packages, wechat.SignType_MD5, timeStamp, client.ApiKey)
  339. zhios_pay_logx.Info("wxRsp.PrepayId:" + wxRsp.PrepayId)
  340. zhios_pay_logx.Info("wxRsp.PrepayId:" + wxRsp.PrepayId)
  341. zhios_pay_logx.Info("wxRsp.PrepayId:" + openid)
  342. res := map[string]string{
  343. "appid": client.AppId,
  344. "partnerid": client.MchId,
  345. "prepayid": wxRsp.PrepayId,
  346. "sign": paySign,
  347. "package": "prepay_id=" + wxRsp.PrepayId,
  348. "noncestr": wxRsp.NonceStr,
  349. "timestamp": timeStamp,
  350. }
  351. return res, nil
  352. }
  353. // TradeH5PayV3 is 微信H5支付v3
  354. func TradeH5PayV3(client *wechat.Client, subject, orderID, amount, notifyUrl string) (string, error) {
  355. // 初始化 BodyMap
  356. bm := make(gopay.BodyMap)
  357. bm.Set("nonce_str", util.GetRandomString(32)).
  358. Set("body", subject).
  359. Set("out_trade_no", orderID).
  360. Set("total_fee", amount).
  361. Set("spbill_create_ip", "127.0.0.1").
  362. Set("notify_url", notifyUrl).
  363. Set("trade_type", wechat.TradeType_App).
  364. Set("device_info", "WEB").
  365. Set("sign_type", wechat.SignType_MD5).
  366. SetBodyMap("scene_info", func(bm gopay.BodyMap) {
  367. bm.SetBodyMap("h5_info", func(bm gopay.BodyMap) {
  368. bm.Set("type", "Wap")
  369. bm.Set("wap_url", "https://www.fumm.cc")
  370. bm.Set("wap_name", "H5测试支付")
  371. })
  372. }) /*.Set("openid", "o0Df70H2Q0fY8JXh1aFPIRyOBgu8")*/
  373. // 预下单
  374. wxRsp, err := client.UnifiedOrder(bm)
  375. if err != nil {
  376. _ = zhios_pay_logx.Warn(err)
  377. return "", err
  378. }
  379. // ====APP支付 paySign====
  380. timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
  381. // 获取APP支付的 paySign
  382. // 注意:package 参数因为是固定值,无需开发者再传入
  383. // appId:AppID
  384. // partnerid:partnerid
  385. // nonceStr:随机字符串
  386. // prepayId:统一下单成功后得到的值
  387. // signType:签名方式,务必与统一下单时用的签名方式一致
  388. // timeStamp:时间
  389. // apiKey:API秘钥值
  390. paySign := wechat.GetAppPaySign(client.AppId, client.MchId, wxRsp.NonceStr, wxRsp.PrepayId, wechat.SignType_MD5, timeStamp, client.ApiKey)
  391. return paySign, nil
  392. }
  393. // TradeMiniProgPayV3 is 微信小程序支付v3
  394. func TradeMiniProgPayV3(client *v3.ClientV3, subject, orderID, amount, notifyUrl string) (string, error) {
  395. return "", nil
  396. }