2

我知道这是一个非常古老的 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"
});

此项目被添加,但“描述”值被转换为:

7enzIGZvbyBiYXIgdGVzdA==

如果您使用正常的 az 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>

所以看起来像它的Body > InsertInvoiceLine > InvLine > Description .. 但我不确定我怎么能告诉它不要编码那个特定的字符串。

任何建议将不胜感激。虽然它不是一个主要的显示停止器(因为所有数据都在系统中),但按预期查看项目名称会更好/更容易:)

谢谢!

4

1 回答 1

2

我认为这可能是SOAP::Lite在认为它们不是 ASCII 的特定子集时决定将它们转换为 base64。你会在SOAP/Lite.pm中找到这个启发式SOAP::Serializer

$self->typelookup({
       'base64Binary' =>
          [10, sub {$_[0] =~ /[^\x09\x0a\x0d\x20-\x7f]/ }, 'as_base64Binary'],
       'zerostring' =>
           [12, sub { $_[0] =~ /^0\d+$/ }, 'as_string'],

... many other types ...
        'string' =>
           [100, sub {1}, 'as_string'],
    });

当 SOAP::Lite 不知道对象的类型时,这就会发挥作用,因为没有人告诉过它。我猜想在你的程序的内部,它正在序列化Descriptiontypelookup粘住它的脏手套。

从这里开始你就靠你自己了,因为 SOAP::Lite 并不好玩。我将首先对 SOAP::Lite 进行一些修改,看看您可以追踪什么。将SOAP/Lite.pm文件复制到某处并将该位置放在您的@INC. 这样你就不会弄乱原始文件。

如果您从不想要 base64,它可能就像在typelookup中删除该行一样简单,尽管声明Description类型会更合适(但也可能是兔子的工作洞)。当您进行正确的修复时,快速修复可以发挥作用。

还有 Perlmonk 的冥想如何说服 SOAP::Lite 在响应中以 UTF-8 形式返回 UTF-8 数据?.

于 2016-10-12T16:04:15.543 回答