#perl #soap #soaplite
#perl #soap #soaplite
Вопрос:
Я знаю, что это очень старый модуль Perl (около 5 лет назад с момента последнего обновления). Я нашел это полезным для проекта, который я делаю, хотя он должен быть на Perl. Вместо того, чтобы начинать снизу вверх, я нашел это полезным для изучения основ. Я уже исправил несколько ошибок с ним, но этот я не могу понять
Рассматриваемый модуль: https://github.com/simoncozens/Net-KashFlow
Пример использования с проблемой:
my $kf = Net::KashFlow->new(username => q|foo@bar.com|, password => "xxxx" );
my $i = $kf->create_invoice({
CustomerReference => "0123-1111111", CustomerID => 50108952,
CurrencyCode => "EUR"
}) || die $!;
$i->add_line({
Quantity => 1,
Description => "íéó foo bar test",
Rate => 10,
VatAmount => 4,
VatRate => 0,
CurrencyCode => "GBP"
});
Этот элемент добавляется, но значение «Description» преобразуется в:
7enzIGZvbyBiYXIgdGVzdA==
Если вы используете обычный a-z 0-9, он работает нормально (и отображается правильно). Проблема, по-видимому, заключается в том, что его кодирование в base64, а затем неправильное декодирование на другом конце. Я предполагаю, что KashFlow не собирается «исправлять» это, поэтому это действительно нужно сделать с этой целью. Я не очень знаком с модулем SOAP ::Lite (опять же, кажется, довольно старый модуль!), Но это то, что он использует.
Я думаю, что это та часть, которая касается добавления новой «строки» в счет-фактуру:
InsertInvoiceLine => {
endpoint => 'https://securedwebapp.com/api/service.asmx',
soapaction => 'KashFlow/InsertInvoiceLine',
namespace => 'KashFlow',
parameters => [
SOAP::Data->new(name => 'UserName', type => 'xsd:string', attr => {}),
SOAP::Data->new(name => 'Password', type => 'xsd:string', attr => {}),
SOAP::Data->new(name => 'InvoiceID', type => 'xsd:int', attr => {}),
SOAP::Data->new(name => 'InvLine', type => 'tns:InvoiceLine', attr => {}),=> {})
], # end parameters
}, # end InsertInvoiceLine
Вы можете увидеть структуру здесь:
https://securedwebapp.com/api/service.asmx?op=InsertInvoiceLine
После изучения этого было предложено сообщить SOAP ::Lite, чтобы он не преобразовывал utf8 в base64, используя (я полагаю), что-то вроде:
Структура:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<InsertInvoiceLine xmlns="KashFlow">
<UserName>string</UserName>
<Password>string</Password>
<InvoiceID>int</InvoiceID>
<InvLine>
<Quantity>decimal</Quantity>
<Description>string</Description>
<Rate>decimal</Rate>
<ChargeType>int</ChargeType>
<VatRate>decimal</VatRate>
<VatAmount>decimal</VatAmount>
<ProductID>int</ProductID>
<Sort>int</Sort>
<ProjID>int</ProjID>
<LineID>int</LineID>
<ValuesInCurrency>integer</ValuesInCurrency>
</InvLine>
</InsertInvoiceLine>
</soap:Body>
</soap:Envelope>
Так выглядит его тело> InsertInvoiceLine> InvLine> Description .. но я не уверен, как я могу сказать, чтобы он не кодировал эту конкретную строку.
Любой совет был бы очень признателен. Хотя это не является основным ограничителем показа (поскольку все данные находятся в системе), было бы намного приятнее / проще видеть имена элементов, как и ожидалось 🙂
Спасибо!
Ответ №1:
Я думаю, что это, вероятно, SOAP ::Lite решает преобразовать вещи в base64, когда он думает, что они не являются определенным подмножеством ASCII. Вы найдете эту эвристику в SOAP / Lite.pm в SOAP::Serializer
:
$self->typelookup({
'base64Binary' =>
[10, sub {$_[0] =~ /[^x09x0ax0dx20-x7f]/ }, 'as_base64Binary'],
'zerostring' =>
[12, sub { $_[0] =~ /^0d $/ }, 'as_string'],
... many other types ...
'string' =>
[100, sub {1}, 'as_string'],
});
Это вступает в игру, когда SOAP ::Lite не знает тип объекта, потому что никто его не сообщил. Я предполагаю, что в недрах вашей программы он Description
typelookup
сериализуется и засовывает свои грязные рукавицы.
И отсюда вы сами по себе, потому что SOAP ::Lite — это не весело. Я бы начал с небольшого взлома SOAP ::Lite, чтобы посмотреть, что вы можете отследить. Скопируйте файл SOAP / Lite.pm куда-нибудь и поместите это местоположение в свой @INC
. Таким образом, вы не будете возиться с исходным файлом.
Если вы никогда не хотите использовать base64, это может быть так же просто, как удалить эту строку в typelookup, хотя объявление Description
типа было бы более правильным (но потенциально и кроличьей норой). Быстрое исправление может подождать, пока вы работаете над правильным исправлением.
Существует также размышление Perlmonk о том, как убедить SOAP ::Lite возвращать данные UTF-8 в ответах как UTF-8 ?.
Комментарии:
1. Спасибо за ответ, Брайан. У меня было ощущение, что это будет непросто. Я думаю, что я просто собираюсь заменить «обычные» символы :
tr{ÀÂÄàâäÇçÉÊÈËéêèëÏÌÎïìîÖÔÒöôòÜÛÙüûù}{AAAaaaCcEEEEeeeeIIIiiiOOOoooUUUuuu};
. Это всего лишь серверная система счетов-фактур для меня, поэтому не обязательно, чтобы у них были правильные акценты