| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- package pay
- import (
- "encoding/json"
- "encoding/xml"
- "errors"
- "fmt"
- "github.com/silenceper/wechat/context"
- "github.com/silenceper/wechat/util"
- )
- var payGateway = "https://api.mch.weixin.qq.com/pay/unifiedorder"
- // Pay struct extends context
- type Pay struct {
- *context.Context
- }
- // Params was NEEDED when request unifiedorder
- // 传入的参数,用于生成 prepay_id 的必需参数
- type Params struct {
- TotalFee string
- CreateIP string
- Body string
- Attach string
- OutTradeNo string
- OpenID string
- }
- // Config 是传出用于 jsdk 用的参数
- type Config struct {
- Timestamp int64
- NonceStr string
- PrePayID string
- SignType string
- Sign string
- }
- // notifyResult 是 支付成功后回调返回
- type NotifyResult struct {
- AppID string `xml:"appid,omitempty"`
- Attach string `xml:"attach,omitempty"`
- BankType string `xml:"bank_type,omitempty"`
- FeeType string `xml:"fee_type,omitempty"`
- IsSubscribe string `xml:"is_subscribe,omitempty"`
- MchId string `xml:"mch_id,omitempty"`
- NonceStr string `xml:"nonce_str,omitempty"`
- Openid string `xml:"openid,omitempty"`
- OutTradeNo string `xml:"out_trade_no,omitempty"`
- ResultCode string `xml:"result_code,omitempty"`
- ReturnCode string `xml:"return_code,omitempty"`
- Sign string `xml:"sign,omitempty"`
- SubMchId string `xml:"sub_mch_id,omitempty"`
- TimeEnd string `xml:"time_end,omitempty"`
- TotalFee string `xml:"total_fee,omitempty"`
- CouponFee string `xml:"coupon_fee,omitempty"`
- CouponCount string `xml:"coupon_count,omitempty"`
- CouponType string `xml:"coupon_type,omitempty"`
- CouponId string `xml:"coupon_id,omitempty"`
- TradeType string `xml:"trade_type,omitempty"`
- TransactionId string `xml:"transaction_id,omitempty"`
- }
- // notifyResult 是 支付成功后回调返回
- type NotifyResponse struct {
- ReturnCode string `xml:"return_code"`
- ReturnMsg string `xml:"return_msg"`
- }
- // payResult 是 unifie order 接口的返回
- type payResult struct {
- ReturnCode string `xml:"return_code"`
- ReturnMsg string `xml:"return_msg"`
- AppID string `xml:"appid,omitempty"`
- MchID string `xml:"mch_id,omitempty"`
- NonceStr string `xml:"nonce_str,omitempty"`
- Sign string `xml:"sign,omitempty"`
- ResultCode string `xml:"result_code,omitempty"`
- TradeType string `xml:"trade_type,omitempty"`
- PrePayID string `xml:"prepay_id,omitempty"`
- CodeURL string `xml:"code_url,omitempty"`
- ErrCode string `xml:"err_code,omitempty"`
- ErrCodeDes string `xml:"err_code_des,omitempty"`
- }
- //payRequest 接口请求参数
- type payRequest struct {
- AppID string `xml:"appid"`
- MchID string `xml:"mch_id"`
- DeviceInfo string `xml:"device_info,omitempty"`
- NonceStr string `xml:"nonce_str"`
- Sign string `xml:"sign"`
- SignType string `xml:"sign_type,omitempty"`
- Body string `xml:"body"`
- Detail string `xml:"detail,omitempty"`
- Attach string `xml:"attach,omitempty"` //附加数据
- OutTradeNo string `xml:"out_trade_no"` //商户订单号
- FeeType string `xml:"fee_type,omitempty"` //标价币种
- TotalFee string `xml:"total_fee"` //标价金额
- SpbillCreateIP string `xml:"spbill_create_ip"` //终端IP
- TimeStart string `xml:"time_start,omitempty"` //交易起始时间
- TimeExpire string `xml:"time_expire,omitempty"` //交易结束时间
- GoodsTag string `xml:"goods_tag,omitempty"` //订单优惠标记
- NotifyURL string `xml:"notify_url"` //通知地址
- TradeType string `xml:"trade_type"` //交易类型
- ProductID string `xml:"product_id,omitempty"` //商品ID
- LimitPay string `xml:"limit_pay,omitempty"` //
- OpenID string `xml:"openid,omitempty"` //用户标识
- SceneInfo string `xml:"scene_info,omitempty"` //场景信息
- }
- // NewPay return an instance of Pay package
- func NewPay(ctx *context.Context) *Pay {
- pay := Pay{Context: ctx}
- return &pay
- }
- // PrePayID will request wechat merchant api and request for a pre payment order id
- func (pcf *Pay) PrePayID(p *Params) (prePayID string, err error) {
- nonceStr := util.RandomStr(32)
- tradeType := "JSAPI"
- //tradeType := "MWEB"
- template := "appid=%s&body=%s&mch_id=%s&nonce_str=%s¬ify_url=%s&openid=%s&out_trade_no=%s&spbill_create_ip=%s&total_fee=%s&trade_type=%s&key=%s"
- str := fmt.Sprintf(template, pcf.AppID, p.Body, pcf.PayMchID, nonceStr, pcf.PayNotifyURL, p.OpenID, p.OutTradeNo, p.CreateIP, p.TotalFee, tradeType, pcf.PayKey)
- sign := util.MD5Sum(str)
- request := payRequest{
- AppID: pcf.AppID,
- MchID: pcf.PayMchID,
- NonceStr: nonceStr,
- Sign: sign,
- Body: p.Body,
- OutTradeNo: p.OutTradeNo,
- TotalFee: p.TotalFee,
- SpbillCreateIP: p.CreateIP,
- NotifyURL: pcf.PayNotifyURL,
- TradeType: tradeType,
- OpenID: p.OpenID,
- }
- rawRet, err := util.PostXML(payGateway, request)
- if err != nil {
- return "", errors.New(err.Error() + " parameters : " + str)
- }
- payRet := payResult{}
- err = xml.Unmarshal(rawRet, &payRet)
- s, _ := json.Marshal(payRet)
- fmt.Println("return pay msg:", string(s))
- if err != nil {
- return "", errors.New(err.Error())
- }
- if payRet.ReturnCode == "SUCCESS" {
- //pay success
- if payRet.ResultCode == "SUCCESS" {
- return payRet.PrePayID, nil
- }
- return "", errors.New(payRet.ErrCode + payRet.ErrCodeDes)
- }
- return "", errors.New("[msg : xmlUnmarshalError] [rawReturn : " + string(rawRet) + "] [params : " + str + "] [sign : " + sign + "]")
- }
- type PayResult struct {
- ReturnCode string `xml:"return_code"`
- ReturnMsg string `xml:"return_msg"`
- AppID string `xml:"appid,omitempty"`
- MchID string `xml:"mch_id,omitempty"`
- NonceStr string `xml:"nonce_str,omitempty"`
- Sign string `xml:"sign,omitempty"`
- ResultCode string `xml:"result_code,omitempty"`
- TradeType string `xml:"trade_type,omitempty"`
- PrePayID string `xml:"prepay_id,omitempty"`
- CodeURL string `xml:"code_url,omitempty"`
- ErrCode string `xml:"err_code,omitempty"`
- ErrCodeDes string `xml:"err_code_des,omitempty"`
- }
- func (pcf *Pay) PreNative(p *Params) (*PayResult, error) {
- nonceStr := util.RandomStr(32)
- tradeType := "NATIVE"
- template := "appid=%s&attach=%s&body=%s&mch_id=%s&nonce_str=%s¬ify_url=%s&out_trade_no=%s&spbill_create_ip=%s&total_fee=%s&trade_type=%s&key=%s"
- str := fmt.Sprintf(template, pcf.AppID, p.Attach, p.Body, pcf.PayMchID, nonceStr, pcf.PayNotifyURL, p.OutTradeNo, p.CreateIP, p.TotalFee, tradeType, pcf.PayKey)
- sign := util.MD5Sum(str)
- request := payRequest{
- AppID: pcf.AppID,
- MchID: pcf.PayMchID,
- NonceStr: nonceStr,
- Sign: sign,
- Body: p.Body,
- OutTradeNo: p.OutTradeNo,
- TotalFee: p.TotalFee,
- SpbillCreateIP: p.CreateIP,
- NotifyURL: pcf.PayNotifyURL,
- TradeType: tradeType,
- OpenID: p.OpenID,
- Attach: p.Attach,
- }
- rawRet, err := util.PostXML(payGateway, request)
- if err != nil {
- return nil, errors.New(err.Error() + " parameters : " + str)
- }
- payRet := PayResult{}
- err = xml.Unmarshal(rawRet, &payRet)
- s, _ := json.Marshal(payRet)
- fmt.Println("return pay msg:", string(s))
- if err != nil {
- return nil, errors.New(err.Error())
- }
- if payRet.ReturnCode == "SUCCESS" {
- //pay success
- if payRet.ResultCode == "SUCCESS" {
- return &payRet, nil
- }
- return nil, errors.New(payRet.ErrCode + payRet.ErrCodeDes)
- }
- return nil, errors.New("[msg : xmlUnmarshalError] [rawReturn : " + string(rawRet) + "] [params : " + str + "] [sign : " + sign + "]")
- }
|