Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

225 lines
6.7KB

  1. package main
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "io/ioutil"
  7. "log"
  8. "net/http"
  9. "time"
  10. )
  11. type crmdLead struct {
  12. crmdEntityBase
  13. //ID string `json:"id,omitempty"`
  14. //Name string `json:"name,omitempty"`
  15. //Deleted bool `json:"deleted,omitempty"`
  16. AvatarID string `json:"avatarId,omitempty"`
  17. AvatarName string `json:"avatarName,omotempty"`
  18. SalutationName string `json:"salutationName,omitempty"`
  19. FirstName string `json:"firstName,omitempty"`
  20. LastName string `json:"lastName,omitempty"`
  21. Title string `json:"title,omitempty"`
  22. Status string `json:"status,omitempty"`
  23. Source string `json:"source,omitempty"`
  24. Industry string `json:"industry,omitempty"`
  25. OpportunityAmount int `json:"opportunityAmount,omitempty"`
  26. Website string `json:"website,omitempty"`
  27. AddressStreet string `json:"addressStreet,omitempty"`
  28. AddressCity string `json:"addressCity,omitempty"`
  29. AddressState string `json:"addressState,omitempty"`
  30. AddressCountry string `json:"addressCountry,omitempty"`
  31. AddressPostalCode string `json:"addresPostalCode,omitempty"`
  32. EmailAddress string `json:"emailAddress,omitempty"`
  33. PhoneNumber string `json:"phoneNumber,omitempty"`
  34. DoNotCall bool `json:"doNotCall,omitempty"`
  35. //Description string `json:"description,omitempty"`
  36. //CreatedAt string `json:"createdAt,omitempty"`
  37. //ModifiedAt string `json:"ModifiedAt,omitempty"`
  38. AccountName string `json:"accountName,omitempty"`
  39. Password string `json:"password,omitempty"`
  40. WechatHitxyID string `json:"wechatOpenID,omitempty"`
  41. OpportunityAmountCurrency string `json:"opportunityAmountCurrency,omitempty"`
  42. OpportunityAmountConverted int `json:"opportunityAmountConverted,omitempty"`
  43. EmailAddressData []struct {
  44. EmailAddress string `json:"emailAddress,omitempty"`
  45. Lower string `json:"lower,omitempty"`
  46. Primary bool `json:"primary,omitempty"`
  47. OptOut bool `json:"optOut,omitempty"`
  48. Invalid bool `json:"invalid,omitempty"`
  49. } `json:"emailAddressData,omitempty"`
  50. PhoneNumberData []struct {
  51. PhoneNumber string `json:"phoneNumber,omitempty"`
  52. Primary bool `json:"primary,omitempty"`
  53. Type string `json:"type,omitempty"`
  54. } `json:"phoneNumberData,omitempty"`
  55. //CreatedByID string `json:"createdById,omitempty"`
  56. //CreatedByName string `json:"createdByName,omitempty"`
  57. //ModifiedByID string `json:"modifiedById,omitempty"`
  58. //ModifiedByName string `json:"modifiedByName,omitempty"`
  59. //AssignedUserID string `json:"assignedUserId,omitempty"`
  60. //AssignedUserName string `json:"assignedUserName,omitempty"`
  61. CampaignID string `json:"campaignId,omitempty"`
  62. CreatedAccountID string `json:"createdAccountId,omitempty"`
  63. CreatedContactID string `json:"createdContactId,omitempty"`
  64. CreatedOpportunityID string `json:"createdOpportunityId,omitempty"`
  65. ForceDuplicate bool `json:"forceDuplicate,omitempty"` //when purposely creating duplicated record, we need to set this to true
  66. }
  67. type crmdSearchLead struct {
  68. Total int `json:"total"`
  69. List []crmdLead `json:"list"`
  70. }
  71. func crmFindLeadByOpenID(openID string) (info crmdLead, found bool, err error) {
  72. total, list, err := crmFindEntityByAttr("Lead", "wechatOpenID", openID)
  73. if err != nil {
  74. return
  75. }
  76. if total == 1 {
  77. found = true
  78. info = list.([]crmdLead)[0]
  79. return
  80. }
  81. found = false
  82. if total > 1 {
  83. msg := fmt.Sprintf("wechatOpenID %s has %d record", openID, total)
  84. log.Printf(msg)
  85. }
  86. return
  87. }
  88. func crmGetLead(id string) (r crmdLead, err error) {
  89. entity, err := crmGetEntity("Lead", id)
  90. r = entity.(crmdLead)
  91. return
  92. }
  93. func crmPatchLeadInfo(newInfo crmdLead) (updatedLead crmdLead, err error) {
  94. b, err := json.Marshal(newInfo)
  95. if err != nil {
  96. log.Printf("Failed to Patch new Info for Lead")
  97. log.Println(newInfo)
  98. return
  99. }
  100. newEntity, err := crmUpdateEntity("Lead", newInfo.ID, b)
  101. if err != nil {
  102. return
  103. }
  104. updatedLead, ok := newEntity.(crmdLead)
  105. if !ok {
  106. err = errors.New("Update Lead result in wrong entityType")
  107. }
  108. return
  109. }
  110. func crmLeadSetStatusNew(id string) {
  111. crmLeadSetStatus(id, "New")
  112. }
  113. func crmLeadSetStatusDead(id string) {
  114. crmLeadSetStatus(id, "Dead")
  115. }
  116. func crmLeadSetStatus(id string, status string) {
  117. newLead := crmdLead{}
  118. newLead.ID = id
  119. newLead.Status = status
  120. crmPatchLeadInfo(newLead)
  121. }
  122. //WechatUserList 超过一万个也可能呢。
  123. //Decode Wechat user List {"total":2,"count":2,"data":{"openid":["","OPENID1","OPENID2"]},"next_openid":"NEXT_OPENID"}
  124. type WechatUserList struct {
  125. Total int `json:"total,omitempty"`
  126. Count int `json:"count,omitempty"`
  127. Data struct {
  128. OpenID []string `json:"openid"`
  129. } `json:"data,omitempty"`
  130. NextOpenID string `json:"next_openid,omitempty"`
  131. }
  132. func importExistingWechatUserAsLead() {
  133. //当公众号关注者数量超过10000时,可通过填写next_openid的值,从而多次拉取列表的方式来满足需求。
  134. atk, _ := GetAccessToken()
  135. nextOpenID := ""
  136. url := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/user/get?access_token=%s&next_openid=%s", atk, nextOpenID)
  137. req, err := http.NewRequest("GET", url, nil)
  138. var myClient = &http.Client{Timeout: 20 * time.Second}
  139. r, err := myClient.Do(req)
  140. if err != nil {
  141. log.Printf("Fail to get URL: %s", req.RequestURI)
  142. log.Println(err)
  143. }
  144. defer r.Body.Close()
  145. jsonB, err := ioutil.ReadAll(r.Body)
  146. users := WechatUserList{}
  147. err = json.Unmarshal(jsonB, &users)
  148. if err != nil {
  149. return
  150. }
  151. for _, openID := range users.Data.OpenID {
  152. log.Println(openID)
  153. _, found, err := crmFindLeadByOpenID(openID)
  154. if !found && err == nil {
  155. crmCreateLeadByOpenID(openID)
  156. }
  157. }
  158. }
  159. func crmCreateLeadByOpenID(openID string) (newuser crmdLead, err error) {
  160. info := WechatUserInfo{}
  161. info.getUserInfo(openID, "zh_CN")
  162. return info.registerNewLeadWithInfo(openID)
  163. }
  164. func (m crmdLead) crmLeadConvert2Contact() (newContact crmdContact) {
  165. newContact.convertFromLead(m.ID)
  166. return
  167. }
  168. func (m crmdLead) Save() (newlead crmdLead, err error) {
  169. jsonB, err := json.Marshal(m)
  170. if err != nil {
  171. return
  172. }
  173. if m.ID != "" {
  174. entity, err := crmUpdateEntity("Lead", m.ID, jsonB)
  175. if err != nil {
  176. return newlead, err
  177. }
  178. newlead = entity.(crmdLead)
  179. } else {
  180. entity, err := crmCreateEntity("Lead", jsonB)
  181. if err != nil {
  182. return newlead, err
  183. }
  184. newlead = entity.(crmdLead)
  185. }
  186. return
  187. }
  188. func (m crmdLead) Delete() bool {
  189. if m.ID != "" {
  190. deleted, err := crmDeleteEntity("Lead", m.ID)
  191. return err == nil && deleted == true
  192. }
  193. return false
  194. }
  195. func (m crmdLead) avatarCacheURL() string {
  196. u := CRMConfig.CacheSiteURL + "?a=" + m.AvatarID
  197. return buildSignatureAppend2Url(u, IntraAPIConfig.CRMSecrete)
  198. }