package main import ( "encoding/json" "errors" "fmt" "io/ioutil" "log" "net/http" "time" ) type crmdLead struct { crmdEntityBase //ID string `json:"id,omitempty"` //Name string `json:"name,omitempty"` //Deleted bool `json:"deleted,omitempty"` AvatarID string `json:"avatarId,omitempty"` AvatarName string `json:"avatarName,omitempty"` SalutationName string `json:"salutationName,omitempty"` FirstName string `json:"firstName,omitempty"` LastName string `json:"lastName,omitempty"` Title string `json:"title,omitempty"` Status string `json:"status,omitempty"` Source string `json:"source,omitempty"` Industry string `json:"industry,omitempty"` OpportunityAmount int `json:"opportunityAmount,omitempty"` Website string `json:"website,omitempty"` AddressStreet string `json:"addressStreet,omitempty"` AddressCity string `json:"addressCity,omitempty"` AddressState string `json:"addressState,omitempty"` AddressCountry string `json:"addressCountry,omitempty"` AddressPostalCode string `json:"addresPostalCode,omitempty"` EmailAddress string `json:"emailAddress,omitempty"` PhoneNumber string `json:"phoneNumber,omitempty"` DoNotCall bool `json:"doNotCall,omitempty"` //Description string `json:"description,omitempty"` //CreatedAt string `json:"createdAt,omitempty"` //ModifiedAt string `json:"ModifiedAt,omitempty"` AccountName string `json:"accountName,omitempty"` Password string `json:"password,omitempty"` WechatHitxyID string `json:"wechatOpenID,omitempty"` OpportunityAmountCurrency string `json:"opportunityAmountCurrency,omitempty"` OpportunityAmountConverted int `json:"opportunityAmountConverted,omitempty"` EmailAddressData []struct { EmailAddress string `json:"emailAddress,omitempty"` Lower string `json:"lower,omitempty"` Primary bool `json:"primary,omitempty"` OptOut bool `json:"optOut,omitempty"` Invalid bool `json:"invalid,omitempty"` } `json:"emailAddressData,omitempty"` PhoneNumberData []struct { PhoneNumber string `json:"phoneNumber,omitempty"` Primary bool `json:"primary,omitempty"` Type string `json:"type,omitempty"` } `json:"phoneNumberData,omitempty"` //CreatedByID string `json:"createdById,omitempty"` //CreatedByName string `json:"createdByName,omitempty"` //ModifiedByID string `json:"modifiedById,omitempty"` //ModifiedByName string `json:"modifiedByName,omitempty"` //AssignedUserID string `json:"assignedUserId,omitempty"` //AssignedUserName string `json:"assignedUserName,omitempty"` CampaignID string `json:"campaignId,omitempty"` CreatedAccountID string `json:"createdAccountId,omitempty"` CreatedContactID string `json:"createdContactId,omitempty"` CreatedOpportunityID string `json:"createdOpportunityId,omitempty"` ForceDuplicate bool `json:"forceDuplicate,omitempty"` //when purposely creating duplicated record, we need to set this to true } type crmdSearchLead struct { Total int `json:"total"` List []crmdLead `json:"list"` } func crmFindLeadByOpenID(openID string) (info crmdLead, found bool, err error) { total, list, err := crmFindEntityByAttr("Lead", "wechatOpenID", openID) if err != nil { return } if total == 1 { found = true info = list.([]crmdLead)[0] return } found = false if total > 1 { msg := fmt.Sprintf("wechatOpenID %s has %d record", openID, total) log.Printf(msg) } return } func crmGetLead(id string) (r crmdLead, err error) { entity, err := crmGetEntity("Lead", id) r = entity.(crmdLead) return } func crmPatchLeadInfo(newInfo crmdLead) (updatedLead crmdLead, err error) { b, err := json.Marshal(newInfo) if err != nil { log.Printf("Failed to Patch new Info for Lead") log.Println(newInfo) return } newEntity, err := crmUpdateEntity("Lead", newInfo.ID, b) if err != nil { return } updatedLead, ok := newEntity.(crmdLead) if !ok { err = errors.New("Update Lead result in wrong entityType") } return } func crmLeadSetStatusNew(id string) { crmLeadSetStatus(id, "New") } func crmLeadSetStatusDead(id string) { crmLeadSetStatus(id, "Dead") } func crmLeadSetStatus(id string, status string) { newLead := crmdLead{} newLead.ID = id newLead.Status = status crmPatchLeadInfo(newLead) } //WechatUserList 超过一万个也可能呢。 //Decode Wechat user List {"total":2,"count":2,"data":{"openid":["","OPENID1","OPENID2"]},"next_openid":"NEXT_OPENID"} type WechatUserList struct { Total int `json:"total,omitempty"` Count int `json:"count,omitempty"` Data struct { OpenID []string `json:"openid"` } `json:"data,omitempty"` NextOpenID string `json:"next_openid,omitempty"` } func importExistingWechatUserAsLead() { //当公众号关注者数量超过10000时,可通过填写next_openid的值,从而多次拉取列表的方式来满足需求。 atk, _ := GetAccessToken() nextOpenID := "" url := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/user/get?access_token=%s&next_openid=%s", atk, nextOpenID) req, err := http.NewRequest("GET", url, nil) var myClient = &http.Client{Timeout: 20 * time.Second} r, err := myClient.Do(req) if err != nil { log.Printf("Fail to get URL: %s", req.RequestURI) log.Println(err) } defer r.Body.Close() jsonB, err := ioutil.ReadAll(r.Body) users := WechatUserList{} err = json.Unmarshal(jsonB, &users) if err != nil { return } for _, openID := range users.Data.OpenID { log.Println(openID) _, found, err := crmFindLeadByOpenID(openID) if !found && err == nil { crmCreateLeadByOpenID(openID) } } } func crmCreateLeadByOpenID(openID string) (newuser crmdLead, err error) { info := WechatUserInfo{} info.getUserInfo(openID, "zh_CN") return info.registerNewLeadWithInfo(openID) } func (m crmdLead) crmLeadConvert2Contact() (newContact crmdContact) { newContact.convertFromLead(m.ID) return } func (m crmdLead) Save() (newlead crmdLead, err error) { jsonB, err := json.Marshal(m) log.Println(string(jsonB)) if err != nil { return } if m.ID != "" { entity, err := crmUpdateEntity("Lead", m.ID, jsonB) if err != nil { return newlead, err } newlead = entity.(crmdLead) } else { entity, err := crmCreateEntity("Lead", jsonB) if err != nil { return newlead, err } newlead = entity.(crmdLead) } return } func (m crmdLead) Delete() bool { if m.ID != "" { deleted, err := crmDeleteEntity("Lead", m.ID) return err == nil && deleted == true } return false } func (m crmdLead) AvatarCacheURL() string { u := CRMConfig.CacheSiteURL + "?a=" + m.AvatarID return buildSignatureAppend2Url(u, IntraAPIConfig.CRMSecrete) }