使用 Blockchain.info API 付款时出现 Runtime Error
支付老李
结论
Blockchain.info Merchant API 要求 amount 和 fee 使用 satoshi(聪)整数,不能直接传入 BTC 小数。
对应关系如下:
0.001 BTC应传入1000000.0001 BTC应传入10000
错误信息 For input string: ".001" 说明服务端在将小数字符串解析为整数时失败了。
修复方法
先把默认参数改为整数:
def SendPayment(
self,
toaddr='TA',
amount=100000,
fromaddr='FA',
shared=0,
fee=10000,
note='test'):
data = {
'address': toaddr,
'amount': amount,
'fee': fee
}
if fromaddr:
data['from'] = fromaddr
if shared == 1:
data['shared'] = 'true'
if note:
data['note'] = note
return self.Call('payment', data)
调用时同样传入 satoshi:
wallet = Wallet(
guid='YOUR_GUID',
password1='YOUR_PASSWORD',
password2='YOUR_SECOND_PASSWORD'
)
result = wallet.SendPayment(
toaddr='DESTINATION_ADDRESS',
amount=100000, # 0.001 BTC
fee=10000 # 0.0001 BTC
)
print(result)
换算关系是:
1 BTC = 100,000,000 satoshi
如果调用方提供的是 BTC 数量,可以用 Decimal 转换,以免受到浮点数精度影响:
from decimal import Decimal
def btc_to_satoshi(value):
return int(Decimal(str(value)) * Decimal('100000000'))
例如:
amount = btc_to_satoshi('0.001')
fee = btc_to_satoshi('0.0001')
print(amount) # 100000
print(fee) # 10000
不建议直接用浮点数换算:
int(0.001 * 100000000)
二进制浮点数可能让某些金额产生意外结果。处理货币金额时,使用字符串和 Decimal 更稳妥。
修正批量发送代码
原来的 SendManyPayment 还有两个问题:
- 类中的方法应通过
self.SendPayment(...)调用。 - 如果
txs是字典,for tx in txs遍历的是键,未必能正确取得地址和金额。
可以将 txs 明确定义为由 (地址, satoshi 金额) 组成的列表:
def SendManyPayment(
self,
txs=None,
fromaddr='FA',
shared=0,
fee=10000,
note='test'):
if txs is None:
txs = []
responses = []
for toaddr, amount in txs:
response = self.SendPayment(
toaddr=toaddr,
amount=amount,
fromaddr=fromaddr,
shared=shared,
fee=fee,
note=note
)
responses.append(response)
return responses
调用示例:
transactions = [
('ADDRESS_1', 100000), # 0.001 BTC
('ADDRESS_2', 250000), # 0.0025 BTC
('ADDRESS_3', 50000) # 0.0005 BTC
]
results = wallet.SendManyPayment(
txs=transactions,
fromaddr='SOURCE_ADDRESS',
fee=10000
)
for result in results:
print(result)
这段代码会依次调用多次 payment API,每次调用都会生成一笔独立付款,并不是一笔包含多个输出的 Bitcoin transaction。
注意事项
amount和fee必须是 satoshi 整数,不能传入'0.001'、.001或0.001。- 不要用
{}作为函数的默认参数。可变默认值会在多次调用之间共享,应改用None。 SendPayment最好返回 API 响应,否则调用方无法获取交易哈希、余额或错误信息。- 批量发送时,应记录每笔请求的成功或失败状态。如果中途失败,之前已经成功广播的交易不会自动撤销。
- 连续发送多笔付款可能重复支付矿工费,也可能遇到未确认输出、余额变化或 API 限速。
- 示例中的 Blockchain.info Merchant API 和第三方
pyblockchain库属于较早期接口。如果服务端接口已有调整,应以实际部署环境对应的 API 文档为准。 - 不要把钱包密码、第二密码或私钥写入代码仓库、日志或异常信息。生产环境应从受保护的配置或密钥管理服务中读取这些信息。
备注:内容仅供参考。
