在YII2中集成BitPay时创建发票遇Token无效/禁用问题求助
YII2集成BitPay时Token无效/禁用问题排查与解决
问题背景
在YII2框架中使用PHP集成BitPay作为支付方式,已参照官方文档完成私钥生成、Token获取步骤,但创建发票时抛出异常:
"BITPAY-INVOICE-CREATE: Failed to create invoice-> failed to serialize Invoice object : failed to retrieve HTTP response body : Token is disabled"
偶尔也会提示Token无效,更换facade或客户端创建方法后问题仍存在。
已执行的操作步骤
- 生成并存储密钥对
$privateKey = PrivateKey::create(<FILENAME>)->generate(); $storageEngine = new EncryptedFilesystemStorage(<PASS>); $storageEngine->persist($privateKey); $privateKey = $storageEngine->load(<FILENAME>); $publicKey = $privateKey->getPublicKey(); $sin = $publicKey->getSin()->__toString();
- 请求POS Token并创建发票
$resourceUrl = 'https://test.bitpay.com/tokens'; $facade = 'pos'; $postData = json_encode([ 'id' => $sin, 'label' => 'Token', 'facade' => $facade ]); $curlCli = curl_init($resourceUrl); curl_setopt($curlCli, CURLOPT_HTTPHEADER, [ 'x-accept-version: 2.0.0', 'Content-Type: application/json', 'x-identity' => $publicKey->__toString(), 'x-signature' => $privateKey->sign($resourceUrl . $postData), ]); curl_setopt($curlCli, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($curlCli, CURLOPT_POSTFIELDS, stripslashes($postData)); curl_setopt($curlCli, CURLOPT_RETURNTRANSFER, true); $result = curl_exec($curlCli); $resultData = json_decode($result, TRUE); curl_close($curlCli); $token = $resultData['data'][0]['token']; // 创建发票代码 $bitpay = new PosClient($token, 'test'); $invoice = new Invoice(<AMOUNT>, Currency::USD); $invoice->setToken($token); $invoice->setToken($token); // 重复设置Token $invoice->setFullNotifications(true); $invoice->setExtendedNotifications(true); $client = new Buyer(); $client->setName(<NAME>); $client->setEmail(<MAIL>); $client->setAddress1(<ADDRESS>); $client->setCountry(<COUNTRY>); $client->setLocality(<CITY>); $client->setNotify(true); $invoice->setBuyer($client); try { $new_invoice = $bitpay->createInvoice($invoice, Facade::POS, false); } catch (\Exception $e) { print_r($e->getMessage()); }
- Token获取响应
{"data": [{"policies": [{"policy":"id", "method":"inactive", "params":["Tf3wXWuwfT1TmenHF21P1nYZ7BeyrYNdiwo"] }], "token":"<TOKEN>", "facade":"pos", "label":"Token", "dateCreated":1696926578101, "pairingExpiration":1697012978101, "pairingCode":"<CODE>" }] }
核心问题与解决步骤
1. 激活未配对的Token
从响应的policies字段可见,当前Token处于**inactive(未激活)**状态,这是报错的直接原因:
- 登录BitPay测试后台
- 进入Settings > API Tokens页面
- 找到响应中返回的
pairingCode,点击激活该Token - 确认Token状态变为
active后再发起发票创建请求
2. 修正Token与客户端的Facade匹配
- 使用
PosClient时,必须确保获取的Token是posfacade类型,且后台已为该Token分配POS权限 - 若切换为
merchant或payoutfacade,需重新生成对应类型的Token并完成激活,避免跨facade使用Token
3. 规范请求签名与参数格式
- 手动生成签名时,严格按照BitPay要求拼接内容:资源URL + 原始POST JSON字符串,不要对JSON做
stripslashes等额外处理,否则会导致签名验证失败 - 确保请求头
x-accept-version与API版本兼容,建议使用SDK默认版本,避免手动设置不匹配的版本号
4. 使用SDK内置流程管理Token
手动用curl请求Token易出现格式错误,建议改用SDK标准方法创建客户端:
// 初始化加密存储引擎 $storageEngine = new EncryptedFilesystemStorage(<PASSWORD>); // 自动处理Token生成、配对与存储 $bitpay = PosClient::create() ->withStorageEngine($storageEngine) ->withEnvironment('test') ->build(); // 首次运行生成配对码,在后台激活后SDK会自动保存有效Token $pairingCode = $bitpay->getPairingCode('pos', 'My Store POS Token');
5. 清理冗余发票参数
- 移除重复的
$invoice->setToken($token)调用,SDK会自动从客户端实例中读取有效Token - 检查发票金额、买家信息等参数格式,确保符合BitPay API的字段要求(如金额为正数、邮箱格式正确)
内容的提问来源于stack exchange,提问作者Deyan
相关产品推荐
相关产品推荐

