支付模块
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.

392 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. // TradeAppPay is 微信APP支付
  99. func TradeAppPay(client *wechat.Client, subject, orderID, amount, notifyUrl string) (map[string]string, error) {
  100. // 初始化 BodyMap
  101. bm := make(gopay.BodyMap)
  102. bm.Set("nonce_str", util.GetRandomString(32)).
  103. Set("body", subject).
  104. Set("out_trade_no", orderID).
  105. Set("total_fee", amount).
  106. Set("spbill_create_ip", "127.0.0.1").
  107. Set("notify_url", notifyUrl).
  108. Set("trade_type", wechat.TradeType_App).
  109. Set("sign_type", wechat.SignType_MD5)
  110. /*.Set("openid", "o0Df70H2Q0fY8JXh1aFPIRyOBgu8")*/
  111. // 预下单
  112. wxRsp, err := client.UnifiedOrder(bm)
  113. if err != nil {
  114. _ = zhios_pay_logx.Warn(err)
  115. return nil, err
  116. }
  117. _, err = wechat.VerifySign(client.ApiKey, wechat.SignType_MD5, wxRsp)
  118. if err != nil {
  119. _ = zhios_pay_logx.Warn(err)
  120. return nil, err
  121. }
  122. //if !ok {
  123. // return nil, errors.New("验签失败")
  124. //}
  125. timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
  126. paySign := wechat.GetAppPaySign(client.AppId, client.MchId, wxRsp.NonceStr, wxRsp.PrepayId, wechat.SignType_MD5, timeStamp, client.ApiKey)
  127. res := map[string]string{
  128. "appid": client.AppId,
  129. "partnerid": client.MchId,
  130. "prepayid": wxRsp.PrepayId,
  131. "sign": paySign,
  132. "package": "Sign=WXPay",
  133. "noncestr": wxRsp.NonceStr,
  134. "timestamp": timeStamp,
  135. }
  136. return res, nil
  137. }
  138. // TradeAppPay is 微信H5支付
  139. func TradeH5Pay(client *wechat.Client, subject, orderID, amount, notifyUrl string) (map[string]string, error) {
  140. // 初始化 BodyMap
  141. bm := make(gopay.BodyMap)
  142. bm.Set("nonce_str", util.GetRandomString(32)).
  143. Set("body", subject).
  144. Set("out_trade_no", orderID).
  145. Set("total_fee", amount).
  146. Set("spbill_create_ip", "121.196.29.49").
  147. Set("notify_url", notifyUrl).
  148. Set("trade_type", wechat.TradeType_H5).
  149. Set("sign_type", wechat.SignType_MD5).
  150. SetBodyMap("scene_info", func(bm gopay.BodyMap) {
  151. bm.SetBodyMap("h5_info", func(bm gopay.BodyMap) {
  152. bm.Set("type", "Wap")
  153. bm.Set("wap_url", "https://www.fumm.cc")
  154. bm.Set("wap_name", "zyos")
  155. })
  156. })
  157. /*.Set("openid", "o0Df70H2Q0fY8JXh1aFPIRyOBgu8")*/
  158. // 预下单
  159. wxRsp, err := client.UnifiedOrder(bm)
  160. if err != nil {
  161. _ = zhios_pay_logx.Warn(err)
  162. return nil, err
  163. }
  164. _, err = wechat.VerifySign(client.ApiKey, wechat.SignType_MD5, wxRsp)
  165. if err != nil {
  166. _ = zhios_pay_logx.Warn(err)
  167. return nil, err
  168. }
  169. timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
  170. packages := "prepay_id=" + wxRsp.PrepayId
  171. paySign := wechat.GetH5PaySign(client.AppId, wxRsp.NonceStr, packages, wechat.SignType_MD5, timeStamp, client.ApiKey)
  172. fmt.Println("paySign===", paySign)
  173. r := map[string]string{
  174. "redirect_url": wxRsp.MwebUrl,
  175. }
  176. return r, nil
  177. }
  178. func TradePcPay(client *wechat.Client, subject, orderID, amount, notifyUrl, productId string) (map[string]string, error) {
  179. // 初始化 BodyMap
  180. bm := make(gopay.BodyMap)
  181. bm.Set("nonce_str", util.GetRandomString(32)).
  182. Set("body", subject).
  183. Set("out_trade_no", orderID).
  184. Set("total_fee", amount).
  185. Set("spbill_create_ip", "121.196.29.49").
  186. Set("notify_url", notifyUrl).
  187. Set("product_id", productId).
  188. Set("trade_type", wechat.TradeType_Native).
  189. Set("sign_type", wechat.SignType_MD5)
  190. // 预下单
  191. wxRsp, err := client.UnifiedOrder(bm)
  192. if err != nil {
  193. _ = zhios_pay_logx.Warn(err)
  194. return nil, err
  195. }
  196. QRcode := ""
  197. if wxRsp.CodeUrl != "" {
  198. QRcode = qrcode.GetPNGBase64(wxRsp.CodeUrl)
  199. }
  200. QRcode = strings.ReplaceAll(QRcode, "\u0000", "")
  201. r := map[string]string{
  202. "payQrcode": QRcode,
  203. }
  204. return r, nil
  205. }
  206. // TradeMiniProgPay is 微信小程序支付 ☑️
  207. func TradeMiniProgPay(client *wechat.Client, subject, orderID, amount, notifyUrl, openid string) (map[string]string, error) {
  208. if len(subject) > 127 {
  209. tmpSubject := []rune(subject)
  210. subject = string(tmpSubject[0:44])
  211. }
  212. // 初始化 BodyMap
  213. bm := make(gopay.BodyMap)
  214. bm.Set("nonce_str", util.GetRandomString(32)).
  215. Set("body", subject).
  216. Set("openid", openid).
  217. Set("out_trade_no", orderID).
  218. Set("total_fee", amount).
  219. Set("spbill_create_ip", "127.0.0.1").
  220. Set("notify_url", notifyUrl).
  221. Set("trade_type", wechat.TradeType_Mini).
  222. Set("sign_type", wechat.SignType_MD5)
  223. // 预下单
  224. wxRsp, err := client.UnifiedOrder(bm)
  225. if err != nil {
  226. _ = zhios_pay_logx.Warn(err)
  227. return nil, err
  228. }
  229. fmt.Println(wxRsp)
  230. timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
  231. packages := "prepay_id=" + wxRsp.PrepayId
  232. paySign := wechat.GetMiniPaySign(client.AppId, wxRsp.NonceStr, packages, wechat.SignType_MD5, timeStamp, client.ApiKey)
  233. res := map[string]string{
  234. "appId": client.AppId,
  235. "paySign": paySign,
  236. "signType": wechat.SignType_MD5,
  237. "package": packages,
  238. "nonceStr": wxRsp.NonceStr,
  239. "timeStamp": timeStamp,
  240. }
  241. return res, nil
  242. }
  243. // TradeAppPayV3 is 微信APP支付v3
  244. func TradeAppPayV3(client *v3.ClientV3, subject, orderID, amount, notifyUrl string) (map[string]string, error) {
  245. // 初始化 BodyMap
  246. amountNew := zhios_pay_utils.AnyToFloat64(amount) * 100
  247. bm := make(gopay.BodyMap)
  248. bm.Set("nonce_str", util.GetRandomString(32)).
  249. Set("body", subject).
  250. Set("out_trade_no", orderID).
  251. Set("total_fee", amountNew).
  252. Set("spbill_create_ip", "127.0.0.1").
  253. Set("notify_url", notifyUrl).
  254. Set("trade_type", wechat.TradeType_App).
  255. Set("sign_type", wechat.SignType_MD5)
  256. /*.Set("openid", "o0Df70H2Q0fY8JXh1aFPIRyOBgu8")*/
  257. //// 预下单
  258. //wxRsp, err := v3.UnifiedOrder(bm)
  259. //if err != nil {
  260. // _ = zhios_pay_logx.Warn(err)
  261. // return nil, err
  262. //}
  263. //_, err = wechat.VerifySign(client.ApiKey, wechat.SignType_MD5, wxRsp)
  264. //if err != nil {
  265. // _ = zhios_pay_logx.Warn(err)
  266. // return nil, err
  267. //}
  268. ////if !ok {
  269. //// return nil, errors.New("验签失败")
  270. ////}
  271. //timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
  272. //paySign := wechat.GetAppPaySign(client.AppId, client.MchId, wxRsp.NonceStr, wxRsp.PrepayId, wechat.SignType_MD5, timeStamp, client.ApiKey)
  273. //res := map[string]string{
  274. // "appid": client.AppId,
  275. // "partnerid": client.MchId,
  276. // "prepayid": wxRsp.PrepayId,
  277. // "sign": paySign,
  278. // "package": "Sign=WXPay",
  279. // "noncestr": wxRsp.NonceStr,
  280. // "timestamp": timeStamp,
  281. //}
  282. //return res, nil
  283. return nil, nil
  284. }
  285. //// TradeJSAPIPay is 微信JSAPI支付
  286. func TradeJSAPIPay(client *wechat.Client, subject, orderID, amount, notifyUrl, openid string) (map[string]string, error) {
  287. // 初始化 BodyMap
  288. bm := make(gopay.BodyMap)
  289. bm.Set("nonce_str", util.GetRandomString(32)).
  290. Set("body", subject).
  291. Set("out_trade_no", orderID).
  292. Set("total_fee", amount).
  293. Set("spbill_create_ip", "121.196.29.49").
  294. Set("notify_url", notifyUrl).
  295. Set("trade_type", wechat.TradeType_JsApi).
  296. Set("sign_type", wechat.SignType_MD5).
  297. Set("openid", openid).
  298. SetBodyMap("scene_info", func(bm gopay.BodyMap) {
  299. bm.SetBodyMap("h5_info", func(bm gopay.BodyMap) {
  300. bm.Set("type", "Wap")
  301. bm.Set("wap_url", "https://www.fumm.cc")
  302. bm.Set("wap_name", "zyos")
  303. })
  304. })
  305. // 预下单
  306. wxRsp, err := client.UnifiedOrder(bm)
  307. if err != nil {
  308. _ = zhios_pay_logx.Warn(err)
  309. return nil, err
  310. }
  311. _, err = wechat.VerifySign(client.ApiKey, wechat.SignType_MD5, wxRsp)
  312. if err != nil {
  313. _ = zhios_pay_logx.Warn(err)
  314. return nil, err
  315. }
  316. //if !ok {
  317. // return nil, errors.New("验签失败")
  318. //}
  319. timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
  320. //paySign := wechat.GetAppPaySign(client.AppId, client.MchId, wxRsp.NonceStr, wxRsp.PrepayId, wechat.SignType_MD5, timeStamp, client.ApiKey)
  321. packages := "prepay_id=" + wxRsp.PrepayId
  322. paySign := wechat.GetJsapiPaySign(client.AppId, wxRsp.NonceStr, packages, wechat.SignType_MD5, timeStamp, client.ApiKey)
  323. zhios_pay_logx.Info("wxRsp.PrepayId:" + wxRsp.PrepayId)
  324. zhios_pay_logx.Info("wxRsp.PrepayId:" + wxRsp.PrepayId)
  325. zhios_pay_logx.Info("wxRsp.PrepayId:" + openid)
  326. res := map[string]string{
  327. "appid": client.AppId,
  328. "partnerid": client.MchId,
  329. "prepayid": wxRsp.PrepayId,
  330. "sign": paySign,
  331. "package": "prepay_id=" + wxRsp.PrepayId,
  332. "noncestr": wxRsp.NonceStr,
  333. "timestamp": timeStamp,
  334. }
  335. return res, nil
  336. }
  337. // TradeH5PayV3 is 微信H5支付v3
  338. func TradeH5PayV3(client *wechat.Client, subject, orderID, amount, notifyUrl string) (string, error) {
  339. // 初始化 BodyMap
  340. bm := make(gopay.BodyMap)
  341. bm.Set("nonce_str", util.GetRandomString(32)).
  342. Set("body", subject).
  343. Set("out_trade_no", orderID).
  344. Set("total_fee", amount).
  345. Set("spbill_create_ip", "127.0.0.1").
  346. Set("notify_url", notifyUrl).
  347. Set("trade_type", wechat.TradeType_App).
  348. Set("device_info", "WEB").
  349. Set("sign_type", wechat.SignType_MD5).
  350. SetBodyMap("scene_info", func(bm gopay.BodyMap) {
  351. bm.SetBodyMap("h5_info", func(bm gopay.BodyMap) {
  352. bm.Set("type", "Wap")
  353. bm.Set("wap_url", "https://www.fumm.cc")
  354. bm.Set("wap_name", "H5测试支付")
  355. })
  356. }) /*.Set("openid", "o0Df70H2Q0fY8JXh1aFPIRyOBgu8")*/
  357. // 预下单
  358. wxRsp, err := client.UnifiedOrder(bm)
  359. if err != nil {
  360. _ = zhios_pay_logx.Warn(err)
  361. return "", err
  362. }
  363. // ====APP支付 paySign====
  364. timeStamp := strconv.FormatInt(time.Now().Unix(), 10)
  365. // 获取APP支付的 paySign
  366. // 注意:package 参数因为是固定值,无需开发者再传入
  367. // appId:AppID
  368. // partnerid:partnerid
  369. // nonceStr:随机字符串
  370. // prepayId:统一下单成功后得到的值
  371. // signType:签名方式,务必与统一下单时用的签名方式一致
  372. // timeStamp:时间
  373. // apiKey:API秘钥值
  374. paySign := wechat.GetAppPaySign(client.AppId, client.MchId, wxRsp.NonceStr, wxRsp.PrepayId, wechat.SignType_MD5, timeStamp, client.ApiKey)
  375. return paySign, nil
  376. }
  377. // TradeMiniProgPayV3 is 微信小程序支付v3
  378. func TradeMiniProgPayV3(client *v3.ClientV3, subject, orderID, amount, notifyUrl string) (string, error) {
  379. return "", nil
  380. }