0

Payeezy に接続し、API を介して XML データを転送および受信する必要があるデスクトップ アプリケーション Foxpro 9.0 Executive があります。WinHttpRequest.5.1 を使用して、UPS 住所確認 API から XML データを送受信しました。しかし、SHA-1 HMAC ハッシュ計算ヘッダーに問題があるようです。Foxpro でこれを実現する方法について、サンプル コードを教えてもらえますか? https://support.payeezy.com/hc/en-us/articles/203731149-API-Security-HMAC-Hash

*api.demo.globalgatewaye4.firstdata.com
***************************
If Vartype(loReq)='U'
  Public loReq
ENDIF
lcURL='https://api-cert.payeezy.com/v1/transactions/v12'
lcPassWd ='Password'
lcExactID='ExactID'
lcKeyCode='Keycode'
ldDate=dtos(DATE())
lcDate=SUBSTR(ldDate,1,4)+'-'+SUBSTR(ldDate,5,2)+'-'+SUBSTR(ldDate,7,2)
ltTime=TIME()
lcDateTime=lcDate+'T'+TRANSFORM(ltTime)+'Z'
uri='transaction/v12'
lcTranstype='00'
lcAmount='1299.00'
lctype='visa'
lcname='John Smith'
lncc_no='4788250000028291'
lcExp_Date='1020'
lccvv='123'
lcAddress='21 Jump Street'
lcCity='Los Angeles'
lcZip='90210'
lcPhone='5557891234'
lcOrderno='12345678'
CustID='87654321'
lcTransactionType="00"
lcShip_Name="Customer Name"
XMLRequest='<?xml version="1.0" encoding="utf-8" ?>'+Chr(13)+;
  '<Transaction>'+Chr(13)+;
  '<Transaction_Type>'+lcTranstype+'</Transaction_Type>'+CHR(13)+;
  '<DollarAmount>'+lcAmount+'</DollarAmount>'+CHR(13)+;
  '<Expiry_Date>'+lcExp_Date+'</Expiry_Date>'+CHR(13)+;
  '<CardHolderName>'+lcname+'</CardHolderName>'+Chr(13)+;
  '<Reference_No>'+lcOrderno+'</Reference_No>'+CHR(13)+;
  '<Customer_Ref>'+CustID+'</Customer_Ref>'+CHR(13)+;
  '<Reference_3>'+lcname+'</Reference_3>'+CHR(13)+;
  '<ExactID>'+lcExactID+'</ExactID>'+CHR(13)+;
  '<Password>'+lcPassWd+ '</Password>'+CHR(13)+;
  '<Card_Number>'+lncc_no+'</Card_Number>'+chr(13)+; 
  '</Transaction>'
Hashme='POST'+chr(13)+'SOAP'+chr(13)+XMLRequest+chr(13)+lcDateTime+chr(13)+lcURL
baseHash=STRCONV(Hashme, 13)
loReq = Createobject('WinHttp.WinHttpRequest.5.1')
loReq.SetTimeouts(2500, 2500, 2500, 2500)
loReq.Open('POST', 'https://api-cert.payeezy.com/v1/transactions/v12', .F.)
loReq.SetCredentials(lcExactID, lcPassWd , 0)
loReq.SetRequestHeader('authorization', 'GGE4_API 14:'+lcKeyCode)
loReq.SetRequestHeader('x-gge4-content-sha1',baseHash )
loReq.SetRequestHeader('content-type', 'application/xml')
loReq.SetRequestHeader('accept', 'text/xml')
loReq.Send(XMLRequest)          
Xmltocursor(loReq.responsetext,'Payeezy')
loReq=""
4

2 に答える 2

1

私は First Data の Payeezy チームで働いています。あなたが投稿したサンプル コードでは、REST API ( https://api-cert.payeezy.com ) と SOAP ベースの API (api.demo.globalgatewaye4.firstdata.com )の 2 つの API を混同しているようです。 )

REST API を使用している場合は、PHP で HMAC を生成するサンプル コードを次に示します。

<?php
$apiKey = "<your api key>";
$apiSecret = "<your consumer secret>";
$nonce = "<Crypographically strong random number>";
$timestamp = "<Epoch timestamp in milli seconds>";
$token = "<Merchant Token>";
$payload = "<For POST - Request body / For GET - empty string>";
$data = $apiKey + $nonce + $timestamp + $token + $payload;
$hashAlgorithm = "sha256";

<!-- Make sure the HMAC hash is in hex -->
$hmac = hash_hmac ( $hashAlgorithm , $data , $apiSecret, false );

<!-- Authorization : base64 of hmac hash -->
$authorization = base64_encode($hmac);
ehco $authorization;
?>

SOAP ベースの API を使用している場合、サンプル コードはhttps://support.payeezy.com/hc/en-us/articles/203731149-API-Security-HMAC-Hashにあります。

于 2016-02-01T21:31:29.267 に答える
1

あなたのコードは base64 エンコーディングをm.Hashmeヘッダーauthorizationに詰め込んでいます。あなたが私たちに言ったことから、SHA-1ハッシュを計算し m.Hashme、ハッシュをヘッダーに入れる必要があるようです(base64でエンコードした後)。

Fox には SHA-1 関数が組み込まれていないため、そのためのセカンダリ ソースが必要です。Fox で Win32 CryptAPI を使用することは可能ですが、これは不必要に面倒で非常に苦痛です。FoxPro Foundation Classes (FFC)の_crypt.vcx中にありますが、それは実際には役に立ちません (すべての FFC と同様に、いずれにしても実稼働環境での使用には適していません)。

価値のあるものとして、Win32 CryptAPI と を使用してハッシュ (デフォルト: SHA1) を計算するために使用できる小さな .prg を次に示します_crypt.vcx

#include WinCrypt.h

lparameters cData, nAlgorithmId

with createobject([CCryptAPIWrapper_])
   return .Hash(@m.cData, m.nAlgorithmId)
endwith   

*******************************************************************************
* _CryptAPI.hProviderHandle needs to be hacked to PROTECTED or PUBLIC
* and also most of the member functions called here

define class CCryptAPIWrapper_ as _CryptAPI of _crypt.vcx

   function Init

      * declare missing CryptAPI functions
      declare long CryptGetHashParam in WIN32API long, long, string@, long@, long

      return dodefault()

   procedure Destroy

      if not empty(this.hProviderHandle)
         this.CryptReleaseContext(this.hProviderHandle)
      endif

   function Hash (cData, nAlgorithmId)

      nAlgorithmId = evl(m.nAlgorithmId, dnALG_SID_SHA)

      local hHashContext, cHash

      hHashContext = 0
      cHash = .null.
      try
         this.CryptCreateHash(this.hProviderHandle, nAlgorithmId, 0, 0, @m.hHashContext)
         this.CryptHashData(m.hHashContext, m.cData, len(m.cData), 0)
         cHash = this.RetrieveHashFromContext(m.hHashContext)
      finally
         if not empty(m.hHashContext)
            this.CryptDestroyHash(m.hHashContext)
         endif
      endtry

      return m.cHash

   function RetrieveHashFromContext (hHashContext)

      local cHashSize, nXferSize

      cHashSize = replicate(chr(0), 4)
      nXferSize = len(m.cHashSize)
      CryptGetHashParam(m.hHashContext, dnHP_HASHSIZE, @m.cHashSize, @m.nXferSize, 0)

      assert m.nXferSize == 4

      local nHashSize, cHashData

      nHashSize = extract_UINT32_(m.cHashSize)
      nXferSize = m.nHashSize
      cHashData = space(m.nHashSize)
      CryptGetHashParam(m.hHashContext, dnHP_HASHVAL, @m.cHashData, @m.nXferSize, 0)

      assert m.nXferSize == m.nHashSize

      return m.cHashData

enddefine

*******************************************************************************
* note: BITOR() and BITLSHIFT() give a signed result -> can't use them here

function extract_UINT32_ (s)

   return asc(substr(m.s, 1, 1)) ;
        + asc(substr(m.s, 2, 1)) * 0x100 ;
        + asc(substr(m.s, 3, 1)) * 0x10000 ;
        + asc(substr(m.s, 4, 1)) * 0x1000000

_crypt.vcxこれを使用するには、VFP9 でも classlib が壊れているため、クラス定義の上のコメントで示されているようにハックする必要があります。また、VFP 検索パスには、Fox ホーム ディレクトリとそのサブディレクトリ FFC の両方を含める必要があります。

于 2016-02-01T15:07:33.487 に答える