diff --git a/paypal/constant.go b/paypal/constant.go index 4d1774ed..11c7a1e5 100644 --- a/paypal/constant.go +++ b/paypal/constant.go @@ -59,4 +59,7 @@ const ( createInvoiceTemplate = "/v2/invoicing/templates" // 创建发票模板 POST deleteInvoiceTemplate = "/v2/invoicing/templates/%s" // template_id 删除发票模板 DELETE fullyUpdateInvoiceTemplate = "/v2/invoicing/templates/%s" // template_id 全量更新发票模板 PUT + + // 物流相关 + addTrackingNumber = "/v2/checkout/orders/%s/track" // order_id 授权物流信息 POST ) diff --git a/paypal/model.go b/paypal/model.go index 5dc16381..57f97d96 100644 --- a/paypal/model.go +++ b/paypal/model.go @@ -333,6 +333,15 @@ type Card struct { AuthenticationResult *AuthenticationResult `json:"authentication_result,omitempty"` } +type PurchaseUnitAddress struct { + AddressLine1 string `json:"address_line_1"` + AddressLine2 string `json:"address_line_2"` + AdminArea1 string `json:"admin_area_1"` + AdminArea2 string `json:"admin_area_2"` + PostalCode string `json:"postal_code"` + CountryCode string `json:"country_code"` +} + type Address struct { AddressLine1 string `json:"address_line_1"` AddressLine2 string `json:"address_line_2"` @@ -396,8 +405,26 @@ type PurchaseUnit struct { } type Amount struct { - CurrencyCode string `json:"currency_code"` - Value string `json:"value"` + CurrencyCode string `json:"currency_code"` + Value string `json:"value"` + PurchaseUnitBreakdown PurchaseUnitBreakdown `json:"breakdown"` +} + +type PurchaseUnitBreakdown struct { + //item_total + ItemTotal *FixedPrice `json:"item_total,omitempty"` + // shipping + Shipping *FixedPrice `json:"shipping,omitempty"` + // handling + Handling *FixedPrice `json:"handling,omitempty"` + // tax_total + TaxTotal *FixedPrice `json:"tax_total,omitempty"` + // insurance + Insurance *FixedPrice `json:"insurance,omitempty"` + // shipping_discount + ShippingDiscount *FixedPrice `json:"shipping_discount,omitempty"` + // discount + Discount *FixedPrice `json:"discount,omitempty"` } type Payee struct { @@ -436,9 +463,9 @@ type Discount struct { } type Shipping struct { - Name *Name `json:"name,omitempty"` - Type string `json:"type,omitempty"` // SHIPPING、PICKUP_IN_PERSON - Address *Address `json:"address,omitempty"` + Name *Name `json:"name,omitempty"` + Type string `json:"type,omitempty"` // SHIPPING、PICKUP_IN_PERSON + Address *PurchaseUnitAddress `json:"address,omitempty"` } type Name struct { @@ -967,3 +994,25 @@ type TemplateInfo struct { Items []*Item `json:"items,omitempty"` PrimaryRecipients []*RecipientInfo `json:"primary_recipients,omitempty"` } + +type AddTrackingNumberReq struct { + TrackingNumber string `json:"tracking_number"` + CarrierNameOther string `json:"carrier_name_other"` + Carrier string `json:"carrier"` + CaptureId string `json:"capture_id"` + NotifyPayer bool `json:"notify_payer"` + ShipItem []*ShipItem `json:"items"` +} +type ShipItem struct { + Name string `json:"name"` + Quantity int `json:"quantity"` + Sku string `json:"sku"` + Url string `json:"url"` + ImageUrl string `json:"image_url"` +} +type AddTrackingNumberRsp struct { + Code int `json:"-"` + Error string `json:"-"` + ErrorResponse *ErrorResponse `json:"-"` + Response *OrderDetail `json:"response,omitempty"` +} diff --git a/paypal/request.go b/paypal/request.go index eba614a7..694337e9 100644 --- a/paypal/request.go +++ b/paypal/request.go @@ -31,6 +31,10 @@ func (c *Client) doPayPalGet(ctx context.Context, uri string) (res *http.Respons return res, bs, nil } +func (c *Client) DoPayPalPost(ctx context.Context, bm gopay.BodyMap, path string) (res *http.Response, bs []byte, err error) { + return c.doPayPalPost(ctx, bm, path) +} + func (c *Client) doPayPalPost(ctx context.Context, bm gopay.BodyMap, path string) (res *http.Response, bs []byte, err error) { var url = c.baseUrlProd + path if !c.IsProd { diff --git a/paypal/tracking.go b/paypal/tracking.go new file mode 100644 index 00000000..8a672ce8 --- /dev/null +++ b/paypal/tracking.go @@ -0,0 +1,37 @@ +package paypal + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + + "github.com/go-pay/gopay" +) + +// AddTrackingNumber 添加物流单号 +// Code = 0 is success +// 文档:https://developer.paypal.com/docs/api/orders/v2/#orders_track_create +func (c *Client) AddTrackingNumber(ctx context.Context, orderId string, bm gopay.BodyMap) (ppRsp *AddTrackingNumberRsp, err error) { + if err = bm.CheckEmptyError("tracking_number", "carrier", "capture_id"); err != nil { + return nil, err + } + + url := fmt.Sprintf(addTrackingNumber, orderId) + res, bs, err := c.doPayPalPost(ctx, bm, url) + if err != nil { + return nil, err + } + ppRsp = &AddTrackingNumberRsp{Code: Success} + ppRsp.Response = new(OrderDetail) + if err = json.Unmarshal(bs, ppRsp.Response); err != nil { + return nil, fmt.Errorf("[%w]: %v, bytes: %s", gopay.UnmarshalErr, err, string(bs)) + } + if res.StatusCode != http.StatusCreated { + ppRsp.Code = res.StatusCode + ppRsp.Error = string(bs) + ppRsp.ErrorResponse = new(ErrorResponse) + _ = json.Unmarshal(bs, ppRsp.ErrorResponse) + } + return ppRsp, nil +} diff --git a/paypal/tracking_test.go b/paypal/tracking_test.go new file mode 100644 index 00000000..efdbc81d --- /dev/null +++ b/paypal/tracking_test.go @@ -0,0 +1,45 @@ +package paypal + +import ( + "testing" + + "github.com/go-pay/xlog" + + "github.com/go-pay/gopay" +) + +func TestAddTrackingNumber(t *testing.T) { + var items []*ShipItem + var item = &ShipItem{ + Name: "T-Shirt", + Quantity: 1, + Sku: "sku02", + Url: "https://www.example.com/example.jpg", + ImageUrl: "https://www.example.com/example", + } + items = append(items, item) + + bm := make(gopay.BodyMap) + bm.Set("capture_id", "1DW71051X94135205"). + Set("tracking_number", "UJ639398620YP"). + Set("carrier", "YANWEN"). + Set("items", items) + + xlog.Debug("bm:", bm.JsonBody()) + + ppRsp, err := client.AddTrackingNumber(ctx, "3TH70640XJ5862H", bm) + if err != nil { + xlog.Error(err) + return + } + if ppRsp.Code != Success { + xlog.Debugf("ppRsp.Code: %+v", ppRsp.Code) + xlog.Debugf("ppRsp.Error: %+v", ppRsp.Error) + xlog.Debugf("ppRsp.ErrorResponse: %+v", ppRsp.ErrorResponse) + return + } + xlog.Debugf("ppRsp.Response: %+v", ppRsp.Response) + for _, v := range ppRsp.Response.Links { + xlog.Debugf("ppRsp.Response.Links: %+v", v) + } +}