diff --git a/miniprogram/express/intracity.go b/miniprogram/express/intracity.go new file mode 100644 index 0000000..7c97203 --- /dev/null +++ b/miniprogram/express/intracity.go @@ -0,0 +1,618 @@ +package express + +import ( + "context" + "fmt" + + "github.com/silenceper/wechat/v2/util" +) + +// 同城配送 API URL +// https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/express/business/intracity_service.html +const ( + // 开通门店权限 + intracityApplyURL = "https://api.weixin.qq.com/cgi-bin/express/intracity/apply?access_token=%s" + // 创建门店 + intracityCreateStoreURL = "https://api.weixin.qq.com/cgi-bin/express/intracity/createstore?access_token=%s" + // 查询门店 + intracityQueryStoreURL = "https://api.weixin.qq.com/cgi-bin/express/intracity/querystore?access_token=%s" + // 更新门店 + intracityUpdateStoreURL = "https://api.weixin.qq.com/cgi-bin/express/intracity/updatestore?access_token=%s" + // 门店运费充值 + intracityStoreChargeURL = "https://api.weixin.qq.com/cgi-bin/express/intracity/storecharge?access_token=%s" + // 门店运费退款 + intracityStoreRefundURL = "https://api.weixin.qq.com/cgi-bin/express/intracity/storerefund?access_token=%s" + // 门店运费流水查询 + intracityQueryFlowURL = "https://api.weixin.qq.com/cgi-bin/express/intracity/queryflow?access_token=%s" + // 门店余额查询 + intracityBalanceQueryURL = "https://api.weixin.qq.com/cgi-bin/express/intracity/balancequery?access_token=%s" + // 预下配送单(查询运费) + intracityPreAddOrderURL = "https://api.weixin.qq.com/cgi-bin/express/intracity/preaddorder?access_token=%s" + // 创建配送单 + intracityAddOrderURL = "https://api.weixin.qq.com/cgi-bin/express/intracity/addorder?access_token=%s" + // 查询配送单 + intracityQueryOrderURL = "https://api.weixin.qq.com/cgi-bin/express/intracity/queryorder?access_token=%s" + // 取消配送单 + intracityCancelOrderURL = "https://api.weixin.qq.com/cgi-bin/express/intracity/cancelorder?access_token=%s" + // 模拟配送回调(仅用于测试) + intracityMockNotifyURL = "https://api.weixin.qq.com/cgi-bin/express/intracity/mocknotify?access_token=%s" +) + +// PayMode 充值/扣费主体 +type PayMode string + +const ( + // PayModeStore 门店 + PayModeStore PayMode = "PAY_MODE_STORE" + // PayModeApp 小程序 + PayModeApp PayMode = "PAY_MODE_APP" + // PayModeComponent 服务商 + PayModeComponent PayMode = "PAY_MODE_COMPONENT" +) + +// OrderPattern 运力偏好 +type OrderPattern uint32 + +const ( + // OrderPatternPriceFirst 价格优先 + OrderPatternPriceFirst OrderPattern = 1 + // OrderPatternTransFirst 运力优先 + OrderPatternTransFirst OrderPattern = 2 +) + +// FlowType 流水类型 +type FlowType uint32 + +const ( + // FlowTypeCharge 充值流水 + FlowTypeCharge FlowType = 1 + // FlowTypeConsume 消费流水 + FlowTypeConsume FlowType = 2 + // FlowTypeRefund 退款流水 + FlowTypeRefund FlowType = 3 +) + +// IntracityDeliveryStatus 配送单状态 +type IntracityDeliveryStatus int32 + +const ( + // IntracityDeliveryStatusReady 配送单待接单 + IntracityDeliveryStatusReady IntracityDeliveryStatus = 100 + // IntracityDeliveryStatusPickedUp 配送单待取货 + IntracityDeliveryStatusPickedUp IntracityDeliveryStatus = 101 + // IntracityDeliveryStatusOngoing 配送单配送中 + IntracityDeliveryStatusOngoing IntracityDeliveryStatus = 102 + // IntracityDeliveryStatusFinished 配送单已送达 + IntracityDeliveryStatusFinished IntracityDeliveryStatus = 200 + // IntracityDeliveryStatusCancelled 配送单已取消 + IntracityDeliveryStatusCancelled IntracityDeliveryStatus = 300 + // IntracityDeliveryStatusAbnormal 配送单异常 + IntracityDeliveryStatusAbnormal IntracityDeliveryStatus = 400 +) + +// IntracityAddressInfo 门店地址信息 +type IntracityAddressInfo struct { + Province string `json:"province"` // 省/自治区/直辖市 + City string `json:"city"` // 地级市 + Area string `json:"area"` // 县/县级市/区 + Street string `json:"street"` // 街道 + House string `json:"house"` // 具体门牌号或详细地址 + Lat float64 `json:"lat"` // 门店所在地纬度 + Lng float64 `json:"lng"` // 门店所在地经度 + Phone string `json:"phone"` // 门店联系电话 + Name string `json:"name,omitempty"` // 联系人姓名(收货地址时使用) +} + +// IntracityStoreInfo 门店信息 +type IntracityStoreInfo struct { + WxStoreID string `json:"wx_store_id"` // 微信门店编号 + OutStoreID string `json:"out_store_id"` // 自定义门店编号 + CityID string `json:"city_id"` // 门店所在城市ID + StoreName string `json:"store_name"` // 门店名称 + OrderPattern OrderPattern `json:"order_pattern"` // 运力偏好 + ServiceTransPrefer string `json:"service_trans_prefer"` // 优先使用的运力ID + AddressInfo IntracityAddressInfo `json:"address_info"` // 门店地址信息 +} + +// ============ 门店管理接口 ============ + +// IntracityApply 开通门店权限 +// https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/express/business/intracity_service.html +func (express *Express) IntracityApply(ctx context.Context) error { + accessToken, err := express.GetAccessToken() + if err != nil { + return err + } + + uri := fmt.Sprintf(intracityApplyURL, accessToken) + response, err := util.PostJSONContext(ctx, uri, map[string]interface{}{}) + if err != nil { + return err + } + + return util.DecodeWithCommonError(response, "IntracityApply") +} + +// CreateStoreRequest 创建门店请求参数 +type CreateStoreRequest struct { + OutStoreID string `json:"out_store_id"` // 自定义门店编号 + StoreName string `json:"store_name"` // 门店名称 + OrderPattern OrderPattern `json:"order_pattern,omitempty"` // 运力偏好:1-价格优先,2-运力优先 + ServiceTransPrefer string `json:"service_trans_prefer,omitempty"` // 优先使用的运力ID,order_pattern=2时必填 + AddressInfo IntracityAddressInfo `json:"address_info"` // 门店地址信息 +} + +// CreateStoreResponse 创建门店返回参数 +type CreateStoreResponse struct { + util.CommonError + WxStoreID string `json:"wx_store_id"` // 微信门店编号 + AppID string `json:"appid"` // 小程序appid + OutStoreID string `json:"out_store_id"` // 自定义门店ID +} + +// IntracityCreateStore 创建门店 +func (express *Express) IntracityCreateStore(ctx context.Context, req *CreateStoreRequest) (res CreateStoreResponse, err error) { + accessToken, err := express.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf(intracityCreateStoreURL, accessToken) + response, err := util.PostJSONContext(ctx, uri, req) + if err != nil { + return + } + + err = util.DecodeWithError(response, &res, "IntracityCreateStore") + return +} + +// QueryStoreRequest 查询门店请求参数 +type QueryStoreRequest struct { + WxStoreID string `json:"wx_store_id,omitempty"` // 微信门店编号 + OutStoreID string `json:"out_store_id,omitempty"` // 自定义门店编号 +} + +// QueryStoreResponse 查询门店返回参数 +type QueryStoreResponse struct { + util.CommonError + Total uint32 `json:"total"` // 符合条件的门店总数 + AppID string `json:"appid"` // 小程序appid + StoreList []IntracityStoreInfo `json:"store_list"` // 门店信息列表 +} + +// IntracityQueryStore 查询门店 +func (express *Express) IntracityQueryStore(ctx context.Context, req *QueryStoreRequest) (res QueryStoreResponse, err error) { + accessToken, err := express.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf(intracityQueryStoreURL, accessToken) + response, err := util.PostJSONContext(ctx, uri, req) + if err != nil { + return + } + + err = util.DecodeWithError(response, &res, "IntracityQueryStore") + return +} + +// UpdateStoreKeyInfo 更新门店的key信息 +type UpdateStoreKeyInfo struct { + WxStoreID string `json:"wx_store_id,omitempty"` // 微信门店编号 + OutStoreID string `json:"out_store_id,omitempty"` // 自定义门店编号,二选一 +} + +// UpdateStoreContent 更新门店的内容 +type UpdateStoreContent struct { + StoreName string `json:"store_name,omitempty"` // 门店名称 + OrderPattern OrderPattern `json:"order_pattern,omitempty"` // 运力偏好 + ServiceTransPrefer string `json:"service_trans_prefer,omitempty"` // 优先使用的运力ID + AddressInfo *IntracityAddressInfo `json:"address_info,omitempty"` // 门店地址信息 +} + +// UpdateStoreRequest 更新门店请求参数 +type UpdateStoreRequest struct { + Keys UpdateStoreKeyInfo `json:"keys"` // 门店编号 + Content UpdateStoreContent `json:"content"` // 更新内容 +} + +// IntracityUpdateStore 更新门店 +func (express *Express) IntracityUpdateStore(ctx context.Context, req *UpdateStoreRequest) error { + accessToken, err := express.GetAccessToken() + if err != nil { + return err + } + + uri := fmt.Sprintf(intracityUpdateStoreURL, accessToken) + response, err := util.PostJSONContext(ctx, uri, req) + if err != nil { + return err + } + + return util.DecodeWithCommonError(response, "IntracityUpdateStore") +} + +// ============ 充值退款接口 ============ + +// StoreChargeRequest 门店运费充值请求参数 +type StoreChargeRequest struct { + WxStoreID string `json:"wx_store_id,omitempty"` // 微信门店编号,pay_mode=PAY_MODE_STORE时必传 + ServiceTransID string `json:"service_trans_id"` // 运力ID + Amount uint32 `json:"amount"` // 充值金额,单位:分,50元起充 + PayMode PayMode `json:"pay_mode,omitempty"` // 充值主体 +} + +// StoreChargeResponse 门店运费充值返回参数 +type StoreChargeResponse struct { + util.CommonError + PayURL string `json:"payurl"` // 充值页面地址 + AppID string `json:"appid"` // 小程序appid + WxStoreID string `json:"wx_store_id"` // 微信门店编号 +} + +// IntracityStoreCharge 门店运费充值 +func (express *Express) IntracityStoreCharge(ctx context.Context, req *StoreChargeRequest) (res StoreChargeResponse, err error) { + accessToken, err := express.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf(intracityStoreChargeURL, accessToken) + response, err := util.PostJSONContext(ctx, uri, req) + if err != nil { + return + } + + err = util.DecodeWithError(response, &res, "IntracityStoreCharge") + return +} + +// StoreRefundRequest 门店运费退款请求参数 +type StoreRefundRequest struct { + WxStoreID string `json:"wx_store_id,omitempty"` // 微信门店编号 + PayMode PayMode `json:"pay_mode,omitempty"` // 充值/扣费主体 + ServiceTransID string `json:"service_trans_id"` // 运力ID +} + +// StoreRefundResponse 门店运费退款返回参数 +type StoreRefundResponse struct { + util.CommonError + AppID string `json:"appid"` // 小程序appid + WxStoreID string `json:"wx_store_id"` // 微信门店编号 + RefundAmount uint32 `json:"refund_amount"` // 退款金额,单位:分 +} + +// IntracityStoreRefund 门店运费退款 +func (express *Express) IntracityStoreRefund(ctx context.Context, req *StoreRefundRequest) (res StoreRefundResponse, err error) { + accessToken, err := express.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf(intracityStoreRefundURL, accessToken) + response, err := util.PostJSONContext(ctx, uri, req) + if err != nil { + return + } + + err = util.DecodeWithError(response, &res, "IntracityStoreRefund") + return +} + +// QueryFlowRequest 门店运费流水查询请求参数 +type QueryFlowRequest struct { + WxStoreID string `json:"wx_store_id"` // 微信门店编号 + FlowType FlowType `json:"flow_type"` // 流水类型:1-充值,2-消费,3-退款 + ServiceTransID string `json:"service_trans_id,omitempty"` // 运力ID + BeginTime uint32 `json:"begin_time,omitempty"` // 开始时间戳 + EndTime uint32 `json:"end_time,omitempty"` // 结束时间戳 + PayMode PayMode `json:"pay_mode"` // 扣费主体 +} + +// FlowRecordInfo 流水记录信息 +type FlowRecordInfo struct { + FlowType FlowType `json:"flow_type"` // 流水类型 + AppID string `json:"appid"` // appid + WxStoreID string `json:"wx_store_id"` // 微信门店ID + PayOrderID uint64 `json:"pay_order_id,omitempty"` // 充值订单号 + WxOrderID string `json:"wx_order_id,omitempty"` // 订单ID(消费流水) + ServiceTransID string `json:"service_trans_id"` // 运力ID + OpenID string `json:"openid,omitempty"` // 用户openid(消费流水) + DeliveryStatus int32 `json:"delivery_status,omitempty"` // 运单状态(消费流水) + PayAmount int32 `json:"pay_amount"` // 支付金额,单位:分 + PayTime uint32 `json:"pay_time,omitempty"` // 支付时间 + PayStatus string `json:"pay_status,omitempty"` // 支付状态 + RefundStatus string `json:"refund_status,omitempty"` // 退款状态 + RefundAmount int32 `json:"refund_amount,omitempty"` // 退款金额 + RefundTime uint32 `json:"refund_time,omitempty"` // 退款时间 + DeductAmount int32 `json:"deduct_amount,omitempty"` // 扣除违约金 + CreateTime uint32 `json:"create_time"` // 创建时间 + ConsumeDeadline uint32 `json:"consume_deadline,omitempty"` // 有效截止日期 + BillID string `json:"bill_id,omitempty"` // 运单ID + DeliveryFinishedTime uint32 `json:"delivery_finished_time,omitempty"` // 运单完成配送的时间 +} + +// QueryFlowResponse 门店运费流水查询返回参数 +type QueryFlowResponse struct { + util.CommonError + Total uint32 `json:"total"` // 总数 + FlowList []FlowRecordInfo `json:"flow_list"` // 流水数组 + TotalPayAmt int `json:"total_pay_amt"` // 总支付金额 + TotalRefundAmt int `json:"total_refund_amt"` // 总退款金额 + TotalDeductAmt int `json:"total_deduct_amt"` // 总违约金(消费流水返回) +} + +// IntracityQueryFlow 门店运费流水查询 +func (express *Express) IntracityQueryFlow(ctx context.Context, req *QueryFlowRequest) (res QueryFlowResponse, err error) { + accessToken, err := express.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf(intracityQueryFlowURL, accessToken) + response, err := util.PostJSONContext(ctx, uri, req) + if err != nil { + return + } + + err = util.DecodeWithError(response, &res, "IntracityQueryFlow") + return +} + +// BalanceQueryRequest 门店余额查询请求参数 +type BalanceQueryRequest struct { + WxStoreID string `json:"wx_store_id,omitempty"` // 微信门店编号 + ServiceTransID string `json:"service_trans_id,omitempty"` // 运力ID + PayMode PayMode `json:"pay_mode,omitempty"` // 充值/扣费主体 +} + +// BalanceInfo 余额信息 +type BalanceInfo struct { + ServiceTransID string `json:"service_trans_id"` // 运力ID + Balance int32 `json:"balance"` // 余额,单位:分 +} + +// BalanceQueryResponse 门店余额查询返回参数 +type BalanceQueryResponse struct { + util.CommonError + AppID string `json:"appid"` // 小程序appid + WxStoreID string `json:"wx_store_id"` // 微信门店编号 + BalanceList []BalanceInfo `json:"balance_list"` // 余额列表 +} + +// IntracityBalanceQuery 门店余额查询 +func (express *Express) IntracityBalanceQuery(ctx context.Context, req *BalanceQueryRequest) (res BalanceQueryResponse, err error) { + accessToken, err := express.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf(intracityBalanceQueryURL, accessToken) + response, err := util.PostJSONContext(ctx, uri, req) + if err != nil { + return + } + + err = util.DecodeWithError(response, &res, "IntracityBalanceQuery") + return +} + +// ============ 配送订单接口 ============ + +// CargoInfo 货物信息 +type CargoInfo struct { + Name string `json:"name"` // 货物名称 + Num uint32 `json:"num,omitempty"` // 货物数量 + Price uint32 `json:"price,omitempty"` // 货物价格,单位:分 + Weight uint32 `json:"weight,omitempty"` // 货物重量,单位:克 +} + +// PreAddOrderRequest 预下配送单请求参数 +type PreAddOrderRequest struct { + WxStoreID string `json:"wx_store_id,omitempty"` // 微信门店编号,二选一 + OutStoreID string `json:"out_store_id,omitempty"` // 自定义门店编号,二选一 + UserOpenID string `json:"user_openid"` // 用户openid + UserPhone string `json:"user_phone,omitempty"` // 用户联系电话 + UserName string `json:"user_name,omitempty"` // 用户姓名 + UserLat float64 `json:"user_lat"` // 用户地址纬度 + UserLng float64 `json:"user_lng"` // 用户地址经度 + UserAddress string `json:"user_address"` // 用户详细地址 + ServiceTransID string `json:"service_trans_id,omitempty"` // 运力ID,不传则查询所有运力 + PayMode PayMode `json:"pay_mode,omitempty"` // 充值/扣费主体 + CargoInfo *CargoInfo `json:"cargo_info,omitempty"` // 货物信息 +} + +// TransInfo 运力信息 +type TransInfo struct { + ServiceTransID string `json:"service_trans_id"` // 运力ID + ServiceName string `json:"service_name"` // 运力名称 + Price uint32 `json:"price"` // 配送费用,单位:分 + Distance uint32 `json:"distance"` // 配送距离,单位:米 + Errcode int `json:"errcode"` // 错误码,0表示成功 + Errmsg string `json:"errmsg"` // 错误信息 +} + +// PreAddOrderResponse 预下配送单返回参数 +type PreAddOrderResponse struct { + util.CommonError + WxStoreID string `json:"wx_store_id"` // 微信门店编号 + AppID string `json:"appid"` // 小程序appid + TransList []TransInfo `json:"trans_list"` // 运力列表 +} + +// IntracityPreAddOrder 预下配送单(查询运费) +func (express *Express) IntracityPreAddOrder(ctx context.Context, req *PreAddOrderRequest) (res PreAddOrderResponse, err error) { + accessToken, err := express.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf(intracityPreAddOrderURL, accessToken) + response, err := util.PostJSONContext(ctx, uri, req) + if err != nil { + return + } + + err = util.DecodeWithError(response, &res, "IntracityPreAddOrder") + return +} + +// AddOrderRequest 创建配送单请求参数 +type AddOrderRequest struct { + WxStoreID string `json:"wx_store_id,omitempty"` // 微信门店编号,二选一 + OutStoreID string `json:"out_store_id,omitempty"` // 自定义门店编号,二选一 + OutOrderID string `json:"out_order_id"` // 自定义订单号,需唯一 + ServiceTransID string `json:"service_trans_id,omitempty"` // 运力ID + UserOpenID string `json:"user_openid"` // 用户openid + UserPhone string `json:"user_phone"` // 用户联系电话 + UserName string `json:"user_name"` // 用户姓名 + UserLat float64 `json:"user_lat"` // 用户地址纬度 + UserLng float64 `json:"user_lng"` // 用户地址经度 + UserAddress string `json:"user_address"` // 用户详细地址 + PayMode PayMode `json:"pay_mode,omitempty"` // 充值/扣费主体 + CargoInfo *CargoInfo `json:"cargo_info,omitempty"` // 货物信息 + OrderDetailPath string `json:"order_detail_path,omitempty"` // 订单详情页路径 + CallbackURL string `json:"callback_url,omitempty"` // 配送状态回调URL + UseInsurance uint32 `json:"use_insurance,omitempty"` // 是否使用保价:0-不使用,1-使用 + InsuranceValue uint32 `json:"insurance_value,omitempty"` // 保价金额,单位:分 + ExpectTime uint32 `json:"expect_time,omitempty"` // 期望送达时间戳 + Remark string `json:"remark,omitempty"` // 备注 +} + +// AddOrderResponse 创建配送单返回参数 +type AddOrderResponse struct { + util.CommonError + WxOrderID string `json:"wx_order_id"` // 微信订单号 + AppID string `json:"appid"` // 小程序appid + WxStoreID string `json:"wx_store_id"` // 微信门店编号 + OutOrderID string `json:"out_order_id"` // 自定义订单号 + ServiceTransID string `json:"service_trans_id"` // 运力ID + BillID string `json:"bill_id"` // 运力订单号 + Price uint32 `json:"price"` // 配送费用,单位:分 + Distance uint32 `json:"distance"` // 配送距离,单位:米 +} + +// IntracityAddOrder 创建配送单 +func (express *Express) IntracityAddOrder(ctx context.Context, req *AddOrderRequest) (res AddOrderResponse, err error) { + accessToken, err := express.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf(intracityAddOrderURL, accessToken) + response, err := util.PostJSONContext(ctx, uri, req) + if err != nil { + return + } + + err = util.DecodeWithError(response, &res, "IntracityAddOrder") + return +} + +// QueryOrderRequest 查询配送单请求参数 +type QueryOrderRequest struct { + WxOrderID string `json:"wx_order_id,omitempty"` // 微信订单号,二选一 + OutOrderID string `json:"out_order_id,omitempty"` // 自定义订单号,二选一 + WxStoreID string `json:"wx_store_id,omitempty"` // 微信门店编号 + OutStoreID string `json:"out_store_id,omitempty"` // 自定义门店编号 +} + +// RiderInfo 骑手信息 +type RiderInfo struct { + Name string `json:"name"` // 骑手姓名 + Phone string `json:"phone"` // 骑手电话 + RiderCode string `json:"rider_code"` // 骑手编号 + RiderImgURL string `json:"rider_img_url"` // 骑手头像URL +} + +// QueryOrderResponse 查询配送单返回参数 +type QueryOrderResponse struct { + util.CommonError + WxOrderID string `json:"wx_order_id"` // 微信订单号 + AppID string `json:"appid"` // 小程序appid + WxStoreID string `json:"wx_store_id"` // 微信门店编号 + OutOrderID string `json:"out_order_id"` // 自定义订单号 + ServiceTransID string `json:"service_trans_id"` // 运力ID + BillID string `json:"bill_id"` // 运力订单号 + DeliveryStatus IntracityDeliveryStatus `json:"delivery_status"` // 配送状态 + Price uint32 `json:"price"` // 配送费用,单位:分 + Distance uint32 `json:"distance"` // 配送距离,单位:米 + CreateTime uint32 `json:"create_time"` // 订单创建时间 + RiderInfo *RiderInfo `json:"rider_info"` // 骑手信息 + FinishTime uint32 `json:"finish_time"` // 订单完成时间 +} + +// IntracityQueryOrder 查询配送单 +func (express *Express) IntracityQueryOrder(ctx context.Context, req *QueryOrderRequest) (res QueryOrderResponse, err error) { + accessToken, err := express.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf(intracityQueryOrderURL, accessToken) + response, err := util.PostJSONContext(ctx, uri, req) + if err != nil { + return + } + + err = util.DecodeWithError(response, &res, "IntracityQueryOrder") + return +} + +// CancelOrderRequest 取消配送单请求参数 +type CancelOrderRequest struct { + WxOrderID string `json:"wx_order_id,omitempty"` // 微信订单号,二选一 + OutOrderID string `json:"out_order_id,omitempty"` // 自定义订单号,二选一 + WxStoreID string `json:"wx_store_id,omitempty"` // 微信门店编号 + OutStoreID string `json:"out_store_id,omitempty"` // 自定义门店编号 + CancelReason string `json:"cancel_reason,omitempty"` // 取消原因 +} + +// CancelOrderResponse 取消配送单返回参数 +type CancelOrderResponse struct { + util.CommonError + WxOrderID string `json:"wx_order_id"` // 微信订单号 + RefundAmount int32 `json:"refund_amount"` // 退款金额,单位:分 + DeductAmount int32 `json:"deduct_amount"` // 扣除违约金,单位:分 +} + +// IntracityCancelOrder 取消配送单 +func (express *Express) IntracityCancelOrder(ctx context.Context, req *CancelOrderRequest) (res CancelOrderResponse, err error) { + accessToken, err := express.GetAccessToken() + if err != nil { + return + } + + uri := fmt.Sprintf(intracityCancelOrderURL, accessToken) + response, err := util.PostJSONContext(ctx, uri, req) + if err != nil { + return + } + + err = util.DecodeWithError(response, &res, "IntracityCancelOrder") + return +} + +// MockNotifyRequest 模拟配送回调请求参数(仅用于测试) +type MockNotifyRequest struct { + WxOrderID string `json:"wx_order_id"` // 微信订单号 + DeliveryStatus IntracityDeliveryStatus `json:"delivery_status"` // 配送状态 +} + +// IntracityMockNotify 模拟配送回调(仅用于测试) +func (express *Express) IntracityMockNotify(ctx context.Context, req *MockNotifyRequest) error { + accessToken, err := express.GetAccessToken() + if err != nil { + return err + } + + uri := fmt.Sprintf(intracityMockNotifyURL, accessToken) + response, err := util.PostJSONContext(ctx, uri, req) + if err != nil { + return err + } + + return util.DecodeWithCommonError(response, "IntracityMockNotify") +} diff --git a/miniprogram/miniprogram.go b/miniprogram/miniprogram.go index 8d20ebf..1f93f5d 100644 --- a/miniprogram/miniprogram.go +++ b/miniprogram/miniprogram.go @@ -197,3 +197,8 @@ func (miniProgram *MiniProgram) GetExpress() *express.Express { func (miniProgram *MiniProgram) GetOCR() *ocr.OCR { return ocr.NewOCR(miniProgram.ctx) } + +// GetIntracity 同城配送接口 +func (miniProgram *MiniProgram) GetIntracity() *express.Express { + return express.NewExpress(miniProgram.ctx) +}