如何解决PayPal沙盒到实时交易搜索API无效?
NB:我相信我遇到的问题与一般的PayPal API问题有关,但无论如何我都会包括我的R代码:
我已经使用PayPal交易搜索API在R中编写了一些代码。它只是获取交易并将其显示在数据框(表)中。
这与我的Sandbox凭据配合正常(它显示了我在那里进行的一项交易)。但是,当我更改为实时凭证时,即使关联的实时帐户中有更多的交易,也没有数据返回。
要“上线”,我的代码将请求URL更改为“ https://api.paypal.com”,并将用户名和密码更改为实时凭据。它什么也没做。
我想知道是否需要采取其他措施?我已经确保在Live App设置下勾选了相关框(因此在Live App中勾选了Transaction API)。我还假设开发者帐户/实时应用程序与其列出的PayPal帐户电子邮件相关联,因此将从该(真实)帐户中提取交易。
library(curl)
library(lubridate)
library(rjson)
library(magrittr)
library(dplyr)
# https://cran.r-project.org/web/packages/curl/vignettes/intro.html
# https://developer.paypal.com/docs/integration/direct/transaction-search/
# https://developer.paypal.com/docs/integration/direct/payments/paypal-payments/#
sandbox.creds <- list(username = "sandbox_username",password = "sandbox_password")
live.creds <- list(username = "live_username",password = "live_password")
# instantiate vars
api_url <- " "
user_pwd <- " "
access.token <<- NA
access.token.expires <<- NA
live.or.sandbox <- function(live) {
# set these vars to NA whenever this function is called
# otherwise the live vs. sandbox API will not find the access token
access.token <<- NA
access.token.expires <<- NA
if (live == TRUE) {
print("setting to live credentials")
api_url <<- "https://api.paypal.com"
user_pwd <<- paste0(live.creds[[1]],":",live.creds[[2]])
}
else {
print("setting to sandbox credentials")
api_url <<- "https://api.sandbox.paypal.com"
user_pwd <<- paste0(sandbox.creds[[1]],sandbox.creds[[2]])
}
}
# set live or sandbox
live.or.sandbox(live = TRUE)
# body --------------------------------------------------------------------
get.access.token <- function() {
req_access_token <- curl::new_handle() %>%
handle_setopt(copypostfields = "grant_type=client_credentials",userpwd = user_pwd,verbose=TRUE,httpauth = 1L) %>%
handle_setheaders("Accept" = "application/json","Accept-Language" = "en_US") %>%
curl_fetch_memory(url = paste0(api_url,"/v1/oauth2/token")) %$% content %>%
rawToChar %>% rjson::fromJSON()
access.token.expires <<- lubridate::as_datetime(lubridate::as_datetime(Sys.time()) + lubridate::dseconds(req_access_token$expires_in))
access.token <<- req_access_token$access_token
}
get.access.token.if.current.not.expired <- function() {
current_time <- lubridate::as_datetime(Sys.time())
cat("access token state: ",access.token)
# only request a new access token if one hasn't been generated yet and if previous requests haven't expired
if (is.na(access.token)) {
print("no access token")
get.access.token()
}
else {
print("already access token")
if(access.token.expires < as_date(Sys.time())) {
print("last access token has expired")
print("get new access token")
get.access.token()
}
else {
print("use old access token")
cat("time left is ",as.integer(difftime(access.token.expires,as_datetime(Sys.time()),units = "secs")))
}
}
}
make.transaction.request <- function(start_date,end_date) {
# check if new access token required
get.access.token.if.current.not.expired()
bearer.access.token <- paste0("Bearer ",access.token)
req_transactions <- new_handle() %>%
handle_setheaders("Accept" = "application/json","Authorization" = bearer.access.token) %>%
curl_fetch_memory(url = paste0(api_url,"/v1/reporting/transactions?fields=all&start_date=",start_date,"&end_date=",end_date,"&fields=all")) %$% content %>%
rawToChar %>% rjson::fromJSON()
print("transaction request")
print(req_transactions)
# just return transaction details
req_transactions$transaction_details
}
format.date.rfc339 <- function(date) {
format(lubridate::as_datetime(date),"%Y-%m-%dT%H:%M:%SZ")
}
# current date in required rfc 339 format
# the maximum date range is 30,so several requests must be made to go beyond this
return.transactions <- function(number_months,tidy_transactions,live) {
if(live == TRUE) {
live.or.sandbox(live = TRUE)
}
else {
live.or.sandbox(live = FALSE)
}
# a month here really means 30 days.
# thus this function returns number_months * 30 days backwards from the present
current_date <- lubridate::as_datetime(Sys.time())
# convert dates to rfc339 format
dates <- lapply(1:number_months,function(x) format.date.rfc339(current_date - ddays((x*30))) )
# get a transaction request for each date range
res <- list()
for (i in 1:number_months) {
if (i < number_months) {
start_date <- dates[[i+1]]
end_date <- dates[[i]]
res[[i]] <- make.transaction.request(start_date,end_date)
}
}
if (tidy_transactions == TRUE) {
transactions <- bind_cols(res)
names(transactions) <- c("transaction_id","transaction_event_code","date","transaction_updated_date","currency_code","value","transaction_status","transaction_subject","value2","protection_eligibility")
transactions <- transactions[,c("transaction_id","value")]
transactions <- transactions %>% mutate(value = sapply(value,function(x) paste0("£",x)),date = sapply(date,function(x) format(as_date(x),format="%B %d %Y"))
)
}
else {
res
}
}
transactions_live <- return.transactions(4,tidy_transactions = FALSE,live = TRUE)
# empty
transactions_sandbox <- return.transactions(4,live = FALSE)
这是我在实时模式下收到的回复:
* Connection 90 seems to be dead!
* Closing connection 90
* Trying 66.211.168.123...
* TCP_NODELAY set
* Connected to api.paypal.com (66.211.168.123) port 443 (#91)
* ALPN,offering h2
* ALPN,offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/cert.pem
CApath: none
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN,server accepted to use http/1.1
* Server certificate:
* subject: C=US; ST=California; L=San Jose; O=PayPal,Inc.; OU=PayPal Production; CN=api.paypal.com
* start date: Jul 28 00:00:00 2020 GMT
* expire date: Aug 2 12:00:00 2022 GMT
* subjectAltName: host "api.paypal.com" matched cert's "api.paypal.com"
* issuer: C=US; O=DigiCert Inc; OU=www.digicert.com; CN=DigiCert SHA2 High Assurance Server CA
* SSL certificate verify ok.
* Server auth using Basic with user 'my_username'
> POST /v1/oauth2/token HTTP/1.1
Host: api.paypal.com
Authorization: Basic blahblahQVZtUWtXlcasdklsdS3VTME93sadjksdjpYlRSXzE2Si11LTVBS19DYnFVX1BlWlBQREcwT25OeTVSTHdQOTVyV0F4WUasdjasdoOUM4bzluQmN6MGg5ckFzbWQ=
User-Agent: RStudio Desktop (1.2.5033); R (3.6.3 x86_64-apple-darwin15.6.0 x86_64 darwin15.6.0)
Accept-Encoding: deflate,gzip
Accept: application/json
Accept-Language: en_US
Content-Length: 29
Content-Type: application/x-www-form-urlencoded
* upload completely sent off: 29 out of 29 bytes
< HTTP/1.1 200 OK
< Content-Type: application/json
< Content-Length: 972
< Connection: keep-alive
< Date: Mon,26 Oct 2020 13:05:54 GMT
< Cache-Control: max-age=0,no-cache,no-store,must-revalidate
< Paypal-Debug-Id: 431a3fb2c4f43
< X-Paypal-Token-Service: IAAS
< Strict-Transport-Security: max-age=31536000; includeSubDomains
<
* Connection #91 to host api.paypal.com left intact
除了“严格传输安全”标头外,这似乎与沙盒模式下的相同:
* Connection 91 seems to be dead!
* Closing connection 91
* Connection 92 seems to be dead!
* Closing connection 92
* Trying 173.0.82.78...
* TCP_NODELAY set
* Connected to api.sandbox.paypal.com (173.0.82.78) port 443 (#93)
* ALPN,server did not agree to a protocol
* Server certificate:
* subject: C=US; ST=California; L=San Jose; O=PayPal,Inc.; OU=PayPal Production; CN=api.sandbox.paypal.com
* start date: Jul 27 00:00:00 2020 GMT
* expire date: Aug 1 12:00:00 2022 GMT
* subjectAltName: host "api.sandbox.paypal.com" matched cert's "api.sandbox.paypal.com"
* issuer: C=US; O=DigiCert Inc; OU=www.digicert.com; CN=DigiCert SHA2 High Assurance Server CA
* SSL certificate verify ok.
* Server auth using Basic with user 'sandbox_username'
> POST /v1/oauth2/token HTTP/1.1
Host: api.sandbox.paypal.com
Authorization: Basic blahblahT1I3MmJrSk5asjdkasjdkasjdksajkdjaskjdksajdkjsakdadkpasdUDF6cDBscjlnTWxaMXBScnl2WmR2YU91cGM=
User-Agent: RStudio Desktop (1.2.5033); R (3.6.3 x86_64-apple-darwin15.6.0 x86_64 darwin15.6.0)
Accept-Encoding: deflate,gzip
Accept: application/json
Accept-Language: en_US
Content-Length: 29
Content-Type: application/x-www-form-urlencoded
* upload completely sent off: 29 out of 29 bytes
< HTTP/1.1 200 OK
< Cache-Control: max-age=0,must-revalidate
< Content-Length: 972
< Content-Type: application/json
< Date: Mon,26 Oct 2020 15:07:46 GMT
< Paypal-Debug-Id: 89a06d70502df
< X-Paypal-Token-Service: IAAS
<
* Connection #93 to host api.sandbox.paypal.com left intact
交易通话:
* Found bundle for host api.paypal.com: 0x7f835d4f5810 [can pipeline]
* Could pipeline,but not asked to!
* Re-using existing connection! (#3) with host api.paypal.com
* Connected to api.paypal.com (66.211.168.123) port 443 (#3)
> GET /v1/reporting/transactions?fields=all&start_date=2020-06-28T19:49:23Z&end_date=2020-07-28T19:49:23Z&fields=all HTTP/1.1
Host: api.paypal.com
User-Agent: RStudio Desktop (1.2.5033); R (3.6.3 x86_64-apple-darwin15.6.0 x86_64 darwin15.6.0)
Accept-Encoding: deflate,gzip
Accept: application/json
Authorization: Bearer blahsduas9fuyiwjwf_vX1d_p8n3keJy8ZSvyjZasdkfdkdsfdsLL8MgQf3RN0R9sEHAXystT7EXqlgasdjasdasosCsxjtBotQ
< HTTP/1.1 200 OK
< Content-Type: application/json
< Content-Length: 442
< Connection: keep-alive
< Date: Mon,26 Oct 2020 19:49:25 GMT
< Application_id: APP-09E52asjdasd0071E
< Cache-Control: max-age=0,must-revalidate
< Caller_acct_num: YXGDSFU9DSFBU7TUE
< Paypal-Debug-Id: aadd1bcasduasd239
< Strict-Transport-Security: max-age=31536000; includeSubDomains
<
* Connection #3 to host api.paypal.com left intact
解决方法
当您请求访问令牌时,它需要返回范围https://uri.paypal.com/services/reporting/search/read
。如果还不包括该范围,请在向您的REST应用程序添加“事务搜索”权限后,最多等待9个小时。
如果您不想等待9个小时,请创建一个新的REST应用并在请求第一个访问令牌之前选中“事务搜索”框,该令牌将被缓存9个小时。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。