| 
						
						
						
					 | 
				
				 | 
				
					@ -0,0 +1,337 @@ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					package wechat | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					import ( | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						"encoding/xml" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						"fmt" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						"log" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						"reflect" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						"strings" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						"time" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						"git.tetele.net/tgo/network" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						"git.tetele.net/tgo/crypter" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						"git.tetele.net/tgo/helper" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					//请求支付
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					type PayXml struct { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						XMLName        xml.Name `xml:"xml"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						Appid          string   `xml:"appid"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						MchId          string   `xml:"mch_id"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						DeviceInfo     string   `xml:"device_info"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						NonceStr       string   `xml:"nonce_str"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						Sign           string   `xml:"sign"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						Body           string   `xml:"body"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						OutTradeNo     string   `xml:"out_trade_no"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						TotalFee       int      `xml:"total_fee"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						SpbillCreateIp string   `xml:"spbill_create_ip"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						AuthCode       string   `xml:"auth_code"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					//支付结果
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					type PayReturnXml struct { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						ReturnCode         string `xml:"return_code"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						ReturnMsg          string `xml:"return_msg"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						Appid              string `xml:"appid"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						MchId              string `xml:"mch_id"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						DeviceInfo         string `xml:"device_info"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						NonceStr           string `xml:"nonce_str"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						Sign               string `xml:"sign"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						ResultCode         string `xml:"result_code"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						ErrCode            string `xml:"err_code"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						ErrCodeDes         string `xml:"err_code_des"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						Openid             string `xml:"openid"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						IsSubscribe        string `xml:"is_subscribe"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						TradeType          string `xml:"trade_type"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						BankType           string `xml:"bank_type"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						FeeType            string `xml:"fee_type"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						TotalFee           string `xml:"total_fee"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						SettlementTotalFee string `xml:"settlement_total_fee"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						CouponFee          string `xml:"coupon_fee"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						CashFeeType        string `xml:"cash_fee_type"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						CashFee            string `xml:"cash_fee"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						TransactionId      string `xml:"transaction_id"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						OutTradeNo         string `xml:"out_trade_no"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						Attach             string `xml:"attach"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						TimeEnd            string `xml:"time_end"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						PromotionDetail    string `xml:"promotion_detail"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					//查询支付
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					type QueryXml struct { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						XMLName    xml.Name `xml:"xml"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						Appid      string   `xml:"appid"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						MchId      string   `xml:"mch_id"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						OutTradeNo string   `xml:"out_trade_no"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						NonceStr   string   `xml:"nonce_str"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						Sign       string   `xml:"sign"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					//查询结果
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					type QueryReturnXml struct { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						ReturnCode         string `xml:"return_code"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						ReturnMsg          string `xml:"return_msg"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						Appid              string `xml:"appid"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						MchId              string `xml:"mch_id"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						NonceStr           string `xml:"nonce_str"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						Sign               string `xml:"sign"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						ResultCode         string `xml:"result_code"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						ErrCode            string `xml:"err_code"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						ErrCodeDes         string `xml:"err_code_des"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						DeviceInfo         string `xml:"device_info"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						Openid             string `xml:"openid"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						IsSubscribe        string `xml:"is_subscribe"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						TradeType          string `xml:"trade_type"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						TradeState         string `xml:"trade_state"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						BankType           string `xml:"bank_type"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						TotalFee           string `xml:"total_fee"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						SettlementTotalFee string `xml:"settlement_total_fee"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						FeeType            string `xml:"fee_type"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						CashFee            string `xml:"cash_fee"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						CashFeeType        string `xml:"cash_fee_type"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						CouponFee          string `xml:"coupon_fee"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						CouponCount        string `xml:"coupon_count"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						TransactionId      string `xml:"transaction_id"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						OutTradeNo         string `xml:"out_trade_no"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						Attach             string `xml:"attach"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						TimeEnd            string `xml:"time_end"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						TradeStateDesc     string `xml:"trade_state_desc"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					// 撤消
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					type ReverseXml struct { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						XMLName    xml.Name `xml:"xml"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						Appid      string   `xml:"appid"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						MchId      string   `xml:"mch_id"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						OutTradeNo string   `xml:"out_trade_no"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						NonceStr   string   `xml:"nonce_str"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						Sign       string   `xml:"sign"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					//撤消结果
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					type ReverseReturnXml struct { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						ReturnCode string `xml:"return_code"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						ReturnMsg  string `xml:"return_msg"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						Appid      string `xml:"appid"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						MchId      string `xml:"mch_id"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						NonceStr   string `xml:"nonce_str"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						Sign       string `xml:"sign"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						ResultCode string `xml:"result_code"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						ErrCode    string `xml:"err_code"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						ErrCodeDes string `xml:"err_code_des"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						Recall     string `xml:"recall"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					/** | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					 * 微信二维码支付 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					 * 2022/02/07 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					 * @param device_info 设备号 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					 * @param body 商品描述 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					 * @param out_trade_no 商户订单号 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					 * @param total_fee 订单金额 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					 * @param auth_code 付款码 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					 */ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					func MicroPay(appid, mchid, mch_key, device_info, body, out_trade_no, auth_code, total_fee string) (bool, string, PayReturnXml) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						log.Println("wechat micropay") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						var requestxml PayXml | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						var retXml PayReturnXml | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						requestxml.Appid = appid | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						requestxml.MchId = mchid | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						requestxml.DeviceInfo = device_info | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						requestxml.NonceStr = helper.GetRandomString(30) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						requestxml.Body = body | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						requestxml.OutTradeNo = out_trade_no | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						requestxml.TotalFee = helper.ToInt(helper.FloatMul(total_fee, 100)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						requestxml.SpbillCreateIp = network.GetLocalIp() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						requestxml.AuthCode = auth_code | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						signStr := helper.StringJoin("appid=", requestxml.Appid, "&auth_code=", requestxml.AuthCode, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							"&body=", requestxml.Body, "&device_info=", requestxml.DeviceInfo, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							"&mch_id=", requestxml.MchId, "&nonce_str=", requestxml.NonceStr, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							"&out_trade_no=", requestxml.OutTradeNo, "&spbill_create_ip=", requestxml.SpbillCreateIp, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							"&total_fee=", helper.ToString(requestxml.TotalFee), "&key=", mch_key) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						signMd5 := Md5Str(signStr) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						requestxml.Sign = strings.ToUpper(signMd5) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						reqXmlJson, err := xml.Marshal(requestxml) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						log.Println(requestxml, string(reqXmlJson), err) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						url := "https://api.mch.weixin.qq.com/pay/micropay" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						ret, err := network.SendXml("POST", url, requestxml) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						log.Println("wechat micropay pay result:", string(ret), err) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						if err != nil { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							log.Println("Err:", err) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							return false, "微信支付失败,请检查网络", retXml | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						err = xml.Unmarshal(ret, &retXml) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						if err != nil { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							log.Println("xml Unmarshal Err:", retXml, err) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							return false, "未知的支付结果", retXml | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						if retXml.ResultCode == "SUCCESS" { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							retMap := XmlStructToMap(retXml) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							//验证sign
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							signStr = helper.HttpBuildQuery(retMap) + "&key=" + mch_key | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							sign := strings.ToUpper(Md5Str(signStr)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							if sign != retXml.Sign { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								log.Println("Err:签名错误", string(ret), sign) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								return false, "支付结果签名错误", retXml | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						} else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							return false, retXml.ReturnMsg, retXml | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						return true, "", retXml | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					func MicroPayQuery(appid, mchid, out_trade_no, mch_key string) (bool, string, QueryReturnXml) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						log.Println("wechat micropay query", out_trade_no) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						var requestxml QueryXml | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						var retXml QueryReturnXml | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						requestxml.Appid = appid | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						requestxml.MchId = mchid | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						requestxml.NonceStr = helper.GetRandomString(30) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						requestxml.OutTradeNo = out_trade_no | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						signStr := helper.StringJoin("appid=", requestxml.Appid, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							"&mch_id=", requestxml.MchId, "&nonce_str=", requestxml.NonceStr, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							"&out_trade_no=", requestxml.OutTradeNo, "&key=", mch_key) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						signMd5 := Md5Str(signStr) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						requestxml.Sign = strings.ToUpper(signMd5) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						url := "https://api.mch.weixin.qq.com/pay/orderquery" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						ret, err := network.SendXml("POST", url, requestxml) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						if err != nil { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							log.Println("Err:", err) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							return false, "微信支付失败,请检查网络", retXml | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						err = xml.Unmarshal(ret, &retXml) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						if err != nil { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							log.Println("xml Unmarshal Err:", retXml, err) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							return false, "未知的支付结果", retXml | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						if retXml.ReturnCode == "SUCCESS" { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							retMap := XmlStructToMap(retXml) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							//验证sign
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							signStr = helper.HttpBuildQuery(retMap) + "&key=" + mch_key | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							sign := strings.ToUpper(Md5Str(signStr)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							if sign != retXml.Sign { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								log.Println("Err:签名错误", string(ret), sign) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								return false, "查询支付结果签名错误", retXml | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						} else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							return false, retXml.ReturnMsg, retXml | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						return true, "", retXml | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					/** | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					 * 撤消订单 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					 * 2023/06/13 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					 */ | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					func MicroPayReverse(appid, mchid, out_trade_no, mch_key string) (bool, string, QueryReturnXml) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						log.Println("wechat micropay reverse", out_trade_no) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						var requestxml ReverseXml | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						var retXml ReverseReturnXml | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						requestxml.Appid = appid | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						requestxml.MchId = mchid | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						requestxml.NonceStr = helper.GetRandomString(30) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						requestxml.OutTradeNo = out_trade_no | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						signStr := helper.StringJoin("appid=", requestxml.Appid, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							"&mch_id=", requestxml.MchId, "&nonce_str=", requestxml.NonceStr, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							"&out_trade_no=", requestxml.OutTradeNo, "&key=", mch_key) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						signMd5 := Md5Str(signStr) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						requestxml.Sign = strings.ToUpper(signMd5) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						url := "https://api.mch.weixin.qq.com/secapi/pay/reverse" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						ret, err := network.SendXml("POST", url, requestxml) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						if err != nil { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							log.Println("Err:", err) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							return false, "撤消微信支付失败,请检查网络", retXml | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						err = xml.Unmarshal(ret, &retXml) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						if err != nil { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							log.Println("xml Unmarshal Err:", retXml, err) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							return false, "未知的撤消结果", retXml | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						if retXml.ReturnCode == "SUCCESS" { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							retMap := XmlStructToMap(retXml) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							//验证sign
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							signStr = helper.HttpBuildQuery(retMap) + "&key=" + mch_key | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							sign := strings.ToUpper(Md5Str(signStr)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							if sign != retXml.Sign { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								log.Println("Err:签名错误", string(ret), sign) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								return false, "查询支付结果签名错误", retXml | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						} else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							return false, retXml.ReturnMsg, retXml | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						return true, "", retXml | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					func XmlStructToMap(retXml interface{}) map[string]string { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						t := reflect.TypeOf(retXml) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						v := reflect.ValueOf(retXml) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						//转为map,验签
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						retMap := make(map[string]string) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						var retValue string | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						var tag string | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						for k := 0; k < t.NumField(); k++ { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							if t.Field(k).Name != "Sign" { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								retValue = helper.ToString(v.Field(k).Interface()) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								tag = fmt.Sprintf("%s", t.Field(k).Tag) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								tag = strings.ReplaceAll(tag, "xml:", "") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								tag = strings.ReplaceAll(tag, "\"", "") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								retMap[tag] = retValue | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						return retMap | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} |