Skip to content

Commit

Permalink
add transfer
Browse files Browse the repository at this point in the history
  • Loading branch information
rosbit committed Jul 8, 2019
1 parent 82f91bf commit 04e0b8e
Show file tree
Hide file tree
Showing 11 changed files with 388 additions and 23 deletions.
6 changes: 5 additions & 1 deletion conf/conf-gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
"create-refund": "/create-refund",
"notify-refund": "/notify-refund",
"query-order": "/query-order",
"close-order": "/close-order"
"close-order": "/close-order",
"transfer": "/transfer",
"query-transfer": "/query-transfer"
},
"merchants": [
{
Expand Down Expand Up @@ -75,6 +77,8 @@ type EndpointConf struct {
NotifyRefund string `json:"notify-refund"`
QueryOrder string `json:"query-order"`
CloseOrder string `json:"close-order"`
Transfer string
QueryTransfer string `json:"query-transfer"`
}

type MerchantConf struct {
Expand Down
48 changes: 48 additions & 0 deletions rest/rest-query-transfer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package rest

import (
"net/http"
"go-wxpay-gateway/conf"
"go-wxpay-gateway/wx-pay-api"
)

// POST /query-transfer
/*
{
"appId": "appId of mp/mini-prog",
"payApp": "name-of-app-in-wxpay-gateway",
"tradeNo": "unique-trade-no",
}
*/
func QueryTransfer(w http.ResponseWriter, r *http.Request) {
var queryParam struct {
AppId string
PayApp string
TradeNo string
}
if code, err := _ReadJson(r, &queryParam); err != nil {
_WriteError(w, code, err.Error())
return
}

isSandbox := _IsSandbox(queryParam.PayApp)
mchConf, _, ok := conf.GetAppAttrs(queryParam.PayApp)
if !ok {
_WriteError(w, http.StatusBadRequest, "Unknown pay-app name")
return
}
res, err := wxpay.QueryTransfer(
queryParam.AppId,
mchConf.MchId,
mchConf.MchAppKey,
queryParam.TradeNo,
mchConf.MchCertPemFile,
mchConf.MchKeyPemFile,
isSandbox,
)
if err != nil {
_WriteError(w, http.StatusInternalServerError, err.Error())
return
}
_WriteJson(w, http.StatusOK, res)
}
66 changes: 66 additions & 0 deletions rest/rest-transfer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package rest

import (
"net/http"
"go-wxpay-gateway/conf"
"go-wxpay-gateway/wx-pay-api"
)

// POST /transfer
/*
{
"appId": "appId of mp/mini-prog",
"payApp": "name-of-app-in-wxpay-gateway",
"tradeNo": "unique-trade-no",
"openId": "openid to be transfered",
"userName": "real user name",
"amount": xxx-in-fen,
"desc": "description",
"ip": "ip to create order"
}
*/
func Transfer(w http.ResponseWriter, r *http.Request) {
var transferParam struct {
AppId string
PayApp string
TradeNo string
OpenId string
UserName string
Amount int
Desc string
Ip string
}

if code, err := _ReadJson(r, &transferParam); err != nil {
_WriteError(w, code, err.Error())
return
}

isSandbox := _IsSandbox(transferParam.PayApp)
mchConf, _, ok := conf.GetAppAttrs(transferParam.PayApp)
if !ok {
_WriteError(w, http.StatusBadRequest, "Unknown pay-app name")
return
}

res, err := wxpay.Transfer(
transferParam.AppId,
mchConf.MchId,
mchConf.MchAppKey,
transferParam.TradeNo,
transferParam.OpenId,
transferParam.UserName,
transferParam.Amount,
transferParam.Desc,
transferParam.Ip,
mchConf.MchCertPemFile,
mchConf.MchKeyPemFile,
isSandbox,
)
if err != nil {
_WriteError(w, http.StatusInternalServerError, err.Error())
return
}
_WriteJson(w, http.StatusOK, &res)
}

2 changes: 2 additions & 0 deletions router-gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ func StartService() error {
router.Post(notifyRefundEndpoint, rest.NotifyRefundment)
router.Post(endpoints.QueryOrder, rest.QueryOrder)
router.Post(endpoints.CloseOrder, rest.CloseOrder)
router.Post(endpoints.Transfer, rest.Transfer)
router.Post(endpoints.QueryTransfer,rest.QueryTransfer)

api.UseHandler(router)

Expand Down
48 changes: 27 additions & 21 deletions wx-pay-api/pay_router.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,41 +6,47 @@ import (
"fmt"
)

var _payUrlRouters = map[bool]string{
false: "",
true: "sandboxnew/",
}

const (
UT_UNIFIED_ORDER = iota
UT_ORDER_QUERY
UT_REFUND
UT_ORDER_CLOSE

unifiedorder_url_fmt = "https://api.mch.weixin.qq.com/%spay/unifiedorder"
orderquery_url_fmt = "https://api.mch.weixin.qq.com/%spay/orderquery"
refund_url_fmt = "https://api.mch.weixin.qq.com/%spay/refund"
orderclose_url_fmt = "https://api.mch.weixin.qq.com/%spay/closeorder"
UT_TRANSFER
UT_TRANSFER_QUERY

SECURE_API_ROUTER = "secapi/"
)

var (
_payUrlRouters = map[bool]string{
false: "",
true: "sandboxnew/",
}

_payUrls = map[int]string{
// payment
UT_UNIFIED_ORDER: "https://api.mch.weixin.qq.com/%spay/unifiedorder",
UT_ORDER_QUERY: "https://api.mch.weixin.qq.com/%spay/orderquery",
UT_REFUND: "https://api.mch.weixin.qq.com/%spay/refund",
UT_ORDER_CLOSE: "https://api.mch.weixin.qq.com/%spay/closeorder",
// transfer
UT_TRANSFER: "https://api.mch.weixin.qq.com/%smmpaymkttransfers/promotion/transfers",
UT_TRANSFER_QUERY:"https://api.mch.weixin.qq.com/%smmpaymkttransfers/gettransferinfo",
}
)

func _GetApiUrl(urlType int, isSandbox bool) string {
urlRouter := _payUrlRouters[isSandbox]
urlFmt, ok := _payUrls[urlType]
if !ok {
return ""
}

switch (urlType) {
case UT_UNIFIED_ORDER:
return fmt.Sprintf(unifiedorder_url_fmt, urlRouter)
case UT_ORDER_QUERY:
return fmt.Sprintf(orderquery_url_fmt, urlRouter)
case UT_REFUND:
urlRouter := _payUrlRouters[isSandbox]
if urlType == UT_REFUND {
if urlRouter == "" {
urlRouter = SECURE_API_ROUTER
}
return fmt.Sprintf(refund_url_fmt, urlRouter)
case UT_ORDER_CLOSE:
return fmt.Sprintf(orderclose_url_fmt, urlRouter)
default:
return ""
}
return fmt.Sprintf(urlFmt, urlRouter)
}
50 changes: 50 additions & 0 deletions wx-pay-api/query_transfer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// +build gateway

package wxpay

func postQueryTransfer(tradeNo, appKey, certFile, keyFile string, xml []byte, isSandbox bool) (*QueryTransferResult, error) {
_paymentLog.Printf("[query-transfer] 1. ### Before Querying tradeNo #%s: %s\n", tradeNo, string(xml))
transfer_query_url := _GetApiUrl(UT_TRANSFER_QUERY, isSandbox)
content, err := _CallSecureWxAPI(transfer_query_url, "POST", xml, certFile, keyFile)
if err != nil {
_paymentLog.Printf("[query-transfer] 2. --- Query tradeNo #%s failed: %v\n", tradeNo, err)
return nil, err
}
_paymentLog.Printf("[query-transfer] 2. +++ Result of querying tradeNo #%s: %s\n", tradeNo, string(content))

return ParseQueryTransferResult("query-transfer-result", content, appKey)
}

func QueryTransfer(
appId string,
mchId string,
mchAppKey string,
tradeNo string,
certFile string,
keyFile string,
isSandbox bool,
) (*QueryTransferResult, error) {
/*
if isSandbox {
var err error
if mchAppKey, err = GetSandbox(appId, mchId, mchAppKey); err != nil {
return nil, err
}
}*/
xml := newXmlGenerator("xml")
params := make(map[string]string)

addTag(xml, params, "appid", appId, false)
addTag(xml, params, "mch_id", mchId, false)
addTag(xml, params, "partner_trade_no", tradeNo, false)
addTag(xml, params, "nonce_str", string(_GetRandomBytes(32)), false)
addTag(xml, params, "sign_type", "MD5", false)

// sign
signature := createMd5Signature(params, mchAppKey)
addTag(xml, params, "sign", signature, false)

xmlstr := xml.toXML()

return postQueryTransfer(tradeNo, mchAppKey, certFile, keyFile, xmlstr, isSandbox)
}
3 changes: 3 additions & 0 deletions wx-pay-api/refund_result_params_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ func ParseRefundResultBody(prompt string, body []byte, appKey string) (*RefundRe
if err = m.getString(&params.MchId, "mch_id", true); err != nil {
return nil, err
}
if err = m.getString(&params.ResultCode, "result_code", true); err != nil {
return nil, err
}
m.getString(&params.ErrCode, "err_code", false)
m.getString(&params.ErrCodeDes, "err_code_des", false)
if err = m.getString(&params.TransactionId, "transaction_id", true); err != nil {
Expand Down
60 changes: 60 additions & 0 deletions wx-pay-api/transfer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// +build gateway

package wxpay

import (
"fmt"
)

func Transfer(
appId string,
mchId string,
mchAppKey string,
tradeNo string,
openId string,
userName string,
amount int,
desc string,
ip string,
certFile string,
keyFile string,
isSandbox bool,
) (*TransferResult, error) {
tags := make(map[string]string)
xml := newXmlGenerator("xml")
addTag(xml, tags, "mch_appid", appId, false)
addTag(xml, tags, "mchid", mchId, false)
addTag(xml, tags, "nonce_str", string(_GetRandomBytes(32)), false)
addTag(xml, tags, "partner_trade_no", tradeNo, false)
addTag(xml, tags, "openid", openId, false)
if userName == "" {
addTag(xml, tags, "check_name", "NO_CHECK", false)
} else {
addTag(xml, tags, "check_name", "FORCE_CHECK", false)
addTag(xml, tags, "re_user_name", userName, false)
}
addTag(xml, tags, "amount", fmt.Sprintf("%d", amount), false)
addTag(xml, tags, "desc", desc, false)
addTag(xml, tags, "spbill_create_ip", ip, false)
// sign
signature := createMd5Signature(tags, mchAppKey)
addTag(xml, tags, "sign", signature, false)

xmlstr := xml.toXML()
// fmt.Printf("xml: %s\n", string(xmlstr))

return postTransfer(tradeNo, mchAppKey, certFile, keyFile, xmlstr, isSandbox)
}

func postTransfer(tradeNo, appKey, certFile, keyFile string, xml []byte, isSandbox bool) (*TransferResult, error) {
_paymentLog.Printf("[transfer] 1. ### Before POSTing transfer #%s: %s\n", tradeNo, string(xml))
transfer_url := _GetApiUrl(UT_TRANSFER, isSandbox)
content, err := _CallSecureWxAPI(transfer_url, "POST", xml, certFile, keyFile)
if err != nil {
_paymentLog.Printf("[transfer] 2. --- POST transfer #%s failed: %v\n", tradeNo, err)
return nil, err
}
_paymentLog.Printf("[transfer] 2. +++ Result of POSTing transfer #%s: %s\n", tradeNo, string(content))

return ParseTransferResultBody("transfer result", content, appKey)
}
Loading

0 comments on commit 04e0b8e

Please sign in to comment.