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

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