diff --git a/src/payment/application.go b/src/payment/application.go index eef57ce9..630308fb 100644 --- a/src/payment/application.go +++ b/src/payment/application.go @@ -15,6 +15,7 @@ import ( "github.com/ArtisanCloud/PowerWeChat/v3/src/payment/jssdk" kernel2 "github.com/ArtisanCloud/PowerWeChat/v3/src/payment/kernel" "github.com/ArtisanCloud/PowerWeChat/v3/src/payment/merchant" + "github.com/ArtisanCloud/PowerWeChat/v3/src/payment/merchantService" "github.com/ArtisanCloud/PowerWeChat/v3/src/payment/notify" "github.com/ArtisanCloud/PowerWeChat/v3/src/payment/notify/request" "github.com/ArtisanCloud/PowerWeChat/v3/src/payment/order" @@ -52,8 +53,9 @@ type Payment struct { Reverse *reverse.Client ProfitSharing *profitSharing.Client - Apply4Sub *apply4Sub.Client - Merchant *merchant.Client + Apply4Sub *apply4Sub.Client + Merchant *merchant.Client + MerchantService *merchantService.Client PayScore *payScore.Client @@ -216,6 +218,11 @@ func NewPayment(config *UserConfig) (*Payment, error) { if err != nil { return nil, err } + //-------------- Merchant Service -------------- + app.MerchantService, err = merchantService.RegisterProvider(app) + if err != nil { + return nil, err + } //-------------- Pay Score -------------- app.PayScore, err = payScore.RegisterProvider(app) @@ -284,6 +291,8 @@ func (app *Payment) GetComponent(name string) interface{} { return app.Tax case "Merchant": return app.Merchant + case "MerchantService": + return app.MerchantService case "PayScore": return app.PayScore diff --git a/src/payment/merchantService/client.go b/src/payment/merchantService/client.go new file mode 100644 index 00000000..7b42158c --- /dev/null +++ b/src/payment/merchantService/client.go @@ -0,0 +1,196 @@ +package merchantService + +import ( + "context" + "fmt" + "github.com/ArtisanCloud/PowerLibs/v3/object" + "github.com/ArtisanCloud/PowerWeChat/v3/src/kernel" + response2 "github.com/ArtisanCloud/PowerWeChat/v3/src/kernel/response" + payment "github.com/ArtisanCloud/PowerWeChat/v3/src/payment/kernel" + "github.com/ArtisanCloud/PowerWeChat/v3/src/payment/merchantService/request" + "github.com/ArtisanCloud/PowerWeChat/v3/src/payment/merchantService/response" + "net/http" +) + +type Client struct { + *payment.BaseClient +} + +func NewClient(app *payment.ApplicationPaymentInterface) (*Client, error) { + baseClient, err := payment.NewBaseClient(app) + if err != nil { + return nil, err + } + return &Client{ + baseClient, + }, nil +} + +// 查询投诉单列表 +// https://pay.weixin.qq.com/docs/merchant/apis/consumer-complaint/complaints/list-complaints-v2.html +func (comp *Client) Complaints(ctx context.Context, params *request.RequestComplaints) (*response.ResponseComplaints, error) { + + result := &response.ResponseComplaints{} + + data, _ := object.StructToStringMap(params) + + endpoint := "/v3/merchant-service/complaints-v2" + _, err := comp.Request(ctx, endpoint, data, http.MethodGet, &object.HashMap{}, false, nil, result) + + return result, err +} + +// 查询投诉单详情 +// https://pay.weixin.qq.com/docs/merchant/apis/consumer-complaint/complaints/query-complaint-v2.html +func (comp *Client) QueryComplaint(ctx context.Context, complaintId string) (*response.ResponseQueryComplaint, error) { + + result := &response.ResponseQueryComplaint{} + + endpoint := fmt.Sprintf("/v3/merchant-service/complaints-v2/%s", complaintId) + _, err := comp.Request(ctx, endpoint, nil, http.MethodGet, &object.HashMap{}, false, nil, result) + + return result, err +} + +// 查询投诉单协商历史 +// https://pay.weixin.qq.com/docs/merchant/apis/consumer-complaint/complaints/query-negotiation-history-v2.html +func (comp *Client) QueryNegotiationHistoriesByComplaint(ctx context.Context, complaintId string, limit int8, offset int8) (*response.ResponseQueryNegotiationHistoriesByComplaint, error) { + + result := &response.ResponseQueryNegotiationHistoriesByComplaint{} + + data := &object.StringMap{ + "limit": fmt.Sprintf("%d", limit), + "offset": fmt.Sprintf("%d", offset), + } + + endpoint := fmt.Sprintf("/v3/merchant-service/complaints-v2/%s/negotiation-historys", complaintId) + _, err := comp.Request(ctx, endpoint, data, http.MethodGet, &object.HashMap{}, false, nil, result) + + return result, err +} + +// 创建投诉通知回调 +// https://pay.weixin.qq.com/docs/merchant/apis/consumer-complaint/complaint-notifications/create-complaint-notifications.html +func (comp *Client) CreateComplaintNotifications(ctx context.Context, url string) (*response.ResponseCreateComplaintNotifications, error) { + + result := &response.ResponseCreateComplaintNotifications{} + + data := &object.HashMap{ + "url": url, + } + + endpoint := "/v3/merchant-service/complaint-notifications" + _, err := comp.Request(ctx, endpoint, nil, http.MethodPost, data, false, nil, result) + + return result, err +} + +// 查询投诉通知回调 +// https://pay.weixin.qq.com/docs/merchant/apis/consumer-complaint/complaint-notifications/query-complaint-notifications.html +func (comp *Client) QueryComplaintNotifications(ctx context.Context, complaintId string, limit int8, offset int8) (*response.ResponseCreateComplaintNotifications, error) { + + result := &response.ResponseCreateComplaintNotifications{} + + endpoint := "/v3/merchant-service/complaint-notifications" + _, err := comp.Request(ctx, endpoint, nil, http.MethodGet, &object.HashMap{}, false, nil, result) + + return result, err +} + +// 更新投诉通知回调 +// https://pay.weixin.qq.com/docs/merchant/apis/consumer-complaint/complaint-notifications/update-complaint-notifications.html +func (comp *Client) UpdateComplaintNotifications(ctx context.Context, url string) (*response.ResponseCreateComplaintNotifications, error) { + + result := &response.ResponseCreateComplaintNotifications{} + + data := &object.HashMap{ + "url": url, + } + + endpoint := "/v3/merchant-service/complaint-notifications" + _, err := comp.Request(ctx, endpoint, nil, http.MethodPut, data, false, nil, result) + + return result, err +} + +// 删除投诉通知回调 +// https://pay.weixin.qq.com/docs/merchant/apis/consumer-complaint/complaint-notifications/delete-complaint-notifications.html +func (comp *Client) DeleteComplaintNotifications(ctx context.Context, url string) (*response2.ResponsePayment, error) { + + result := &response2.ResponsePayment{} + + endpoint := "/v3/merchant-service/complaint-notifications" + _, err := comp.Request(ctx, endpoint, nil, http.MethodDelete, &object.HashMap{}, false, nil, result) + + return result, err +} + +// 回复用户 +// https://pay.weixin.qq.com/docs/merchant/apis/consumer-complaint/complaints/response-complaint-v2.html +func (comp *Client) ReplyToUser(ctx context.Context, complaintId string, params *request.RequestReplyToUser) (*response2.ResponsePayment, error) { + + result := &response2.ResponsePayment{} + + data, _ := object.StructToHashMap(params) + + endpoint := fmt.Sprintf("/v3/merchant-service/complaints-v2/%s/response", complaintId) + _, err := comp.Request(ctx, endpoint, nil, http.MethodPost, data, false, nil, result) + + return result, err +} + +// 反馈处理完成 +// https://pay.weixin.qq.com/docs/merchant/apis/consumer-complaint/complaints/complete-complaint-v2.html +func (comp *Client) CompleteFeedback(ctx context.Context, complaintId string) (*response2.ResponsePayment, error) { + + result := &response2.ResponsePayment{} + + endpoint := fmt.Sprintf("/v3/merchant-service/complaints-v2/%s/complete", complaintId) + _, err := comp.Request(ctx, endpoint, nil, http.MethodPost, &object.HashMap{}, false, nil, result) + + return result, err +} + +// 更新退款审批结果 +// https://pay.weixin.qq.com/docs/merchant/apis/consumer-complaint/complaints/complete-complaint-v2.html +func (comp *Client) UpdateFeedback(ctx context.Context, complaintId string, params *request.RequestUpdateFeedback) (*response2.ResponsePayment, error) { + + result := &response2.ResponsePayment{} + + data, _ := object.StructToHashMap(params) + + endpoint := fmt.Sprintf("/v3/merchant-service/complaints-v2/%s/update-refund-progress", complaintId) + _, err := comp.Request(ctx, endpoint, nil, http.MethodPost, data, false, nil, result) + + return result, err +} + +// 图片上传接口 +// https://pay.weixin.qq.com/docs/merchant/apis/consumer-complaint/images/create-images.html +func (comp *Client) UploadImg(ctx context.Context, params *request.RequestMediaUpload) (*response.ResponseMediaUpload, error) { + + result := &response.ResponseMediaUpload{} + + var files *object.HashMap + if params.File != "" { + files = &object.HashMap{ + "file": params.File, + } + } + + var formData *kernel.UploadForm + if params.Meta != nil { + formData = &kernel.UploadForm{ + Contents: []*kernel.UploadContent{ + &kernel.UploadContent{ + Name: "file", + Value: params.Meta.Filename, + }, + }, + } + } + options, _ := object.StructToHashMap(params.Meta) + + _, err := comp.BaseClient.HttpUploadJson(ctx, "/v3/merchant-service/images/upload", files, formData, options, nil, nil, &result) + return result, err +} diff --git a/src/payment/merchantService/provider.go b/src/payment/merchantService/provider.go new file mode 100644 index 00000000..fac2e5a2 --- /dev/null +++ b/src/payment/merchantService/provider.go @@ -0,0 +1,11 @@ +package merchantService + +import ( + "github.com/ArtisanCloud/PowerWeChat/v3/src/payment/kernel" +) + +func RegisterProvider(app kernel.ApplicationPaymentInterface) (*Client, error) { + + return NewClient(&app) + +} diff --git a/src/payment/merchantService/request/request.go b/src/payment/merchantService/request/request.go new file mode 100644 index 00000000..885ac858 --- /dev/null +++ b/src/payment/merchantService/request/request.go @@ -0,0 +1,19 @@ +package request + +type Meta struct { + Filename string `json:"filename"` + Sha256 string `json:"sha256"` +} + +type RequestMediaUpload struct { + File string `json:"file"` + Meta *Meta `json:"meta"` +} + +type RequestComplaints struct { + Limit int8 `json:"limit"` + Offset int8 `json:"offset"` + BeginDate string `json:"begin_date"` + EndDate string `json:"end_date"` + ComplaintedMchId string `json:"complainted_mchid"` +} diff --git a/src/payment/merchantService/request/requestReplyToUser.go b/src/payment/merchantService/request/requestReplyToUser.go new file mode 100644 index 00000000..e9d02efb --- /dev/null +++ b/src/payment/merchantService/request/requestReplyToUser.go @@ -0,0 +1,9 @@ +package request + +type RequestReplyToUser struct { + ComplaintedMchid string `json:"complainted_mchid"` + ResponseContent string `json:"response_content"` + ResponseImages []string `json:"response_images"` + JumpUrl string `json:"jump_url"` + JumpUrlText string `json:"jump_url_text"` +} diff --git a/src/payment/merchantService/request/requestUpdateFeedback.go b/src/payment/merchantService/request/requestUpdateFeedback.go new file mode 100644 index 00000000..21b4d54e --- /dev/null +++ b/src/payment/merchantService/request/requestUpdateFeedback.go @@ -0,0 +1,9 @@ +package request + +type RequestUpdateFeedback struct { + Action string `json:"action"` + LaunchRefundDay int `json:"launch_refund_day"` + RejectReason string `json:"reject_reason"` + RejectMediaList []string `json:"reject_media_list"` + Remark string `json:"remark"` +} diff --git a/src/payment/merchantService/response/response.go b/src/payment/merchantService/response/response.go new file mode 100644 index 00000000..3157b3f4 --- /dev/null +++ b/src/payment/merchantService/response/response.go @@ -0,0 +1,74 @@ +package response + +import ( + "github.com/ArtisanCloud/PowerWeChat/v3/src/kernel/response" + "time" +) + +type ResponseMediaUpload struct { + response.ResponsePayment + MediaId string `json:"media_id"` +} + +type ReturnAddressInfo struct { + ReturnAddress string `json:"return_address"` + Longitude string `json:"longitude"` + Latitude string `json:"latitude"` +} + +type SharePowerInfo struct { + ReturnTime time.Time `json:"return_time"` + ReturnAddressInfo ReturnAddressInfo `json:"return_address_info"` +} + +type AdditionalInfo struct { + Type string `json:"type"` + SharePowerInfo SharePowerInfo `json:"share_power_info"` +} + +type ServiceOrderInfo struct { + OrderId string `json:"order_id"` + OutOrderNo string `json:"out_order_no"` + State string `json:"state"` +} + +type ComplaintMediaList struct { + MediaType string `json:"media_type"` + MediaUrl []string `json:"media_url"` +} + +type ComplainOrderInfo struct { + TransactionId string `json:"transaction_id"` + OutTradeNo string `json:"out_trade_no"` + Amount int `json:"amount"` +} + +type ResponseQueryComplaint struct { + response.ResponsePayment + + ComplaintId string `json:"complaint_id"` + ComplaintTime time.Time `json:"complaint_time"` + ComplaintDetail string `json:"complaint_detail"` + ComplaintState string `json:"complaint_state"` + PayerPhone string `json:"payer_phone"` + ComplaintOrderInfo []ComplainOrderInfo `json:"complaint_order_info"` + ComplaintFullRefunded bool `json:"complaint_full_refunded"` + IncomingUserResponse bool `json:"incoming_user_response"` + UserComplaintTimes int `json:"user_complaint_times"` + ComplaintMediaList []ComplaintMediaList `json:"complaint_media_list"` + ProblemDescription string `json:"problem_description"` + ProblemType string `json:"problem_type"` + ApplyRefundAmount int `json:"apply_refund_amount"` + UserTagList []string `json:"user_tag_list"` + ServiceOrderInfo []ServiceOrderInfo `json:"service_order_info"` + AdditionalInfo AdditionalInfo `json:"additional_info"` +} + +type ResponseComplaints struct { + response.ResponsePayment + + Data []ResponseQueryComplaint `json:"data"` + Limit int `json:"limit"` + Offset int `json:"offset"` + TotalCount int `json:"total_count"` +} diff --git a/src/payment/merchantService/response/responseCreateComplaintNotifications.go b/src/payment/merchantService/response/responseCreateComplaintNotifications.go new file mode 100644 index 00000000..4c3d073f --- /dev/null +++ b/src/payment/merchantService/response/responseCreateComplaintNotifications.go @@ -0,0 +1,6 @@ +package response + +type ResponseCreateComplaintNotifications struct { + MchId string `json:"mchid"` + Url string `json:"url"` +} diff --git a/src/payment/merchantService/response/responseQueryNegotiationHistoriesByComplaint.go b/src/payment/merchantService/response/responseQueryNegotiationHistoriesByComplaint.go new file mode 100644 index 00000000..5af69fcc --- /dev/null +++ b/src/payment/merchantService/response/responseQueryNegotiationHistoriesByComplaint.go @@ -0,0 +1,20 @@ +package response + +import "time" + +type Data struct { + LogId string `json:"log_id"` + Operator string `json:"operator"` + OperateTime time.Time `json:"operate_time"` + OperateType string `json:"operate_type"` + OperateDetails string `json:"operate_details"` + ImageList []string `json:"image_list"` + ComplaintMediaList ComplaintMediaList `json:"complaint_media_list"` +} + +type ResponseQueryNegotiationHistoriesByComplaint struct { + Data []Data `json:"data"` + Limit int `json:"limit"` + Offset int `json:"offset"` + TotalCount int `json:"total_count"` +}