前端之家收集整理的这篇文章主要介绍了
golang实现微信小程序支付服务端,
前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
小程序支付的交互图如下:
商户系统和微信支付系统主要交互:
1、小程序内调用登录接口,获取到用户的openid,api参见公共api【小程序登录API】
2、商户server调用支付统一下单,api参见公共api【统一下单API】
3、商户server调用再次签名,api参见公共api【再次签名】
4、商户server接收支付通知,api参见公共api【支付结果通知API】
5、商户server查询支付结果,api参见公共api【查询订单API】
以下是统一下单API
type WXPayResp struct {
Return_code string `xml:"return_code"`
Return_msg string `xml:"return_msg"`
Nonce_str string `xml:"nonce_str"`
Prepay_id string `xml:"prepay_id"`
}
func (index *IndexController) WxPay(){
info := make(map[string]interface{}, 0)
fmt.Println("访问ip",index.Request.RemoteAddr)
ip := utils.Substr(index.Request.RemoteAddr, 0,strings.Index(index.Request.RemoteAddr,":"))
total_fee,_ := strconv.ParseFloat(index.GetString("total_fee"),64)
openId := index.GetString("openId");
body := "费用说明";
orderNo := index.GetString("orderNo");
nonceStr := time.Now().Format("20060102150405") + string(utils.Krand(4, 0))
var reqMap = make(map[string]interface{}, 0)
reqMap["appid"] = utils.Wx_Appid
reqMap["body"] = body
reqMap["mch_id"] = utils.Wx_Mchid
reqMap["nonce_str"] = nonceStr
reqMap["notify_url"] = "http://test.com.cn/weixinNotice.jspx"
reqMap["openid"] = openId
reqMap["out_trade_no"] = orderNo
reqMap["spbill_create_ip"] = ip
reqMap["total_fee"] = total_fee * 100
reqMap["trade_type"] = "JSAPI"
reqMap["sign"] = WxPayCalcSign(reqMap,utils.WX_KEY)
reqStr := Map2Xml(reqMap)
fmt.Println("请求xml",reqStr)
client := &http.Client{}
req,err := http.NewRequest("POST","https://api.mch.weixin.qq.com/pay/unifiedorder",strings.NewReader(reqStr))
if err != nil {
}
req.Header.Set("Content-Type","text/xml;charset=utf-8")
resp,err := client.Do(req)
defer resp.Body.Close()
body2,err := IoUtil.ReadAll(resp.Body)
if err != nil {
fmt.Println("解析响应内容失败",err)
return
}
fmt.Println("响应数据",string(body2))
var resp1 WXPayResp
err = xml.Unmarshal(body2,&resp1)
if err != nil {
panic(err)
return
}
if strings.ToUpper(resp1.Return_code) == "SUCCESS"{
fmt.Println("预支付申请成功")
var resMap = make(map[string]interface{}, 0)
resMap["appId"] = utils.Wx_Appid
resMap["nonceStr"] = resp1.Nonce_str
resMap["package"] = "prepay_id=" + resp1.Prepay_id
resMap["signType"] = "MD5"
resMap["timeStamp"] = utils.ToStr(time.Now().Unix())
resMap["paySign"] = WxPayCalcSign(resMap,utils.WX_KEY)
fmt.Println("支付参数",resMap)
index.Console(resMap)
}else{
info["msg"] = "微信请求支付失败"
index.Console(info)
}
}
//微信支付计算签名的函数
func WxPayCalcSign(mReq map[string]interface{},key string) (sign string) {
//STEP 1,对key进行升序排序.
sorted_keys := make([]string,0)
for k,_ := range mReq { sorted_keys = append(sorted_keys,k) }
sort.Strings(sorted_keys)
//STEP2,对key=value的键值对用&连接起来,略过空值
var signStrings string
for _,k := range sorted_keys {
logger.Printf("k=%v,v=%v\n",k,mReq[k])
value := fmt.Sprintf("%v",mReq[k])
if value != "" {
signStrings = signStrings + k + "=" + value + "&"
}
}
//STEP3,在键值对的最后加上key=API_KEY
if key != "" {
signStrings = signStrings + "key=" + key
}
fmt.Println("加密前-----",signStrings)
//STEP4,进行MD5签名并且将所有字符转为大写.
md5Ctx := md5.New()
md5Ctx.Write([]byte(signStrings)) //
cipherStr := md5Ctx.Sum(nil)
upperSign := strings.ToUpper(hex.EncodeToString(cipherStr))
fmt.Println("加密后-----",upperSign)
return upperSign
}
func Map2Xml(mReq map[string]interface{}) (xml string) {
sb := bytes.Buffer{}
sb.WriteString("<xml>")
for k,v := range mReq{
sb.WriteString("<"+k+">"+utils.ToStr(v)+"</"+k+">")
}
sb.WriteString("</xml>")
return sb.String()
}