非同期ゲートウェイアダプタの作成
非同期プロセスは、最初のゲートウェイ要求後にプラットフォームが保留中のトランザクションを作成しない同期トランザクションとは異なります。代わりに、ゲートウェイが最終的なトランザクションの状況が含まれる応答を送信した後にのみ、プラットフォームはトランザクションを作成します。同期アダプタの作成については、「同期ゲートウェイアダプタの作成」を参照してください。
- 非同期支払ゲートウェイアダプタの定義
- 最初の支払要求の処理
- 支払ゲートウェイからの通知の処理
- システムデバッグログを使用したゲートウェイ応答のデバッグ。
非同期支払ゲートウェイアダプタ定義
非同期ゲートウェイアダプタクラスでは、PaymentGatewayAdapter インターフェースと PaymentGatewayAsyncAdapter インターフェースの両方を実装する必要があります。アダプタクラスでは、PaymentGatewayAdapter の processRequest メソッドと PaymentGatewayAsyncAdapter の processNotification メソッドも実装する必要があります。
1global with sharing class SampleAdapter implements commercepayments.PaymentGatewayAsyncAdapter, commercepayments.PaymentGatewayAdapter {
2 global SampleAdapter() {}
3
4 global commercepayments.GatewayResponse processRequest(commercepayments.paymentGatewayContext gatewayContext) {
5 }
6
7 global commercepayments.GatewayNotificationResponse processNotification(commercepayments.PaymentGatewayNotificationContext gatewayNotificationContext) {
8 }
9}最初の支払要求の処理
支払プラットフォームは支払 API 要求を受信すると、さらに評価を行うために要求をゲートウェイアダプタに渡します。アダプタは、非同期支払フローの最初のステップを表す processRequest メソッドをコールして要求評価プロセスを開始します。processRequest 実装は 3 つの部分に分けることができます。
最初に、ゲートウェイで理解できる支払要求オブジェクトを作成します。
1commercepayments.RequestType requestType = gatewayContext.getPaymentRequestType();
2if (requestType == commercepayments.RequestType.Capture) {
3 req.setEndpoint('/pal/servlet/Payment/v52/capture');
4 body = buildCaptureRequest((commercepayments.CaptureRequest)gatewayContext.getPaymentRequest());
5} else if (requestType == commercepayments.RequestType.ReferencedRefund) {
6 req.setEndpoint('/pal/servlet/Payment/v52/refund');
7 body = buildRefundRequest((commercepayments.ReferencedRefundRequest)gatewayContext.getPaymentRequest());
8}次に、アダプタが要求を支払ゲートウェイに送信します。
1req.setBody(body);
2req.setMethod('POST');
3commercepayments.PaymentsHttp http = new commercepayments.PaymentsHttp();
4HttpResponse res = null;
5try {
6 res = http.send(req);
7} catch(CalloutException ce) {
8 commercepayments.GatewayErrorResponse error = new commercepayments.GatewayErrorResponse('500', ce.getMessage());
9 return error;
10}1if ( requestType == commercepayments.RequestType.Capture) {
2 // Refer to the end of this doc for sample createCaptureResponse implementation
3 response = createCaptureResponse(res);
4} else if ( requestType == commercepayments.RequestType.ReferencedRefund) {
5 response = createRefundResponse(res);
6}
7return response;支払ゲートウェイからの通知の処理
顧客の銀行がトランザクションを処理して結果をゲートウェイに送信したら、ゲートウェイは最終的なトランザクションの状況を提供する準備ができたことを示す通知をアダプタに送信します。非同期トランザクションフローのこの部分のために、アダプタは processNotification クラスをコールする必要があります。processNotification 実装は 4 つの部分に分けることができます。
最初に、アダプタが通知要求の署名を確認します。署名の確認についての詳細は、[TOPIC] を参照してください。
1private Boolean verifySignature(NotificationRequest requestItem) {
2 String payload = requestItem.pspReference + ':'
3 + (requestItem.originalReference == null ? '' : requestItem.originalReference) + ':'
4 + requestItem.merchantAccountCode + ':'
5 + requestItem.merchantReference + ':'
6 + requestItem.amount.value.intValue() + ':'
7 + requestItem.amount.currencyCode + ':'
8 + requestItem.eventCode + ':'
9 + requestItem.success;
10 String myHMacKey = getHMacKey();
11 String generatedSign = EncodingUtil.base64Encode(Crypto.generateMac('hmacSHA256', Blob.valueOf(payload),
12 EncodingUtil.convertFromHex(myHMacKey)));
13 return generatedSign.equals(requestItem.additionalData.hmacSignature);
14}1commercepayments.PaymentGatewayNotificationRequest gatewayNotificationRequest = gatewayNotificationContext.getPaymentGatewayNotificationRequest();
2Blob request = gatewayNotificationRequest.getRequestBody();
3SampleNotificationRequest notificationRequest = SampleNotificationRequest.parse(request.toString().replace('currency', 'currencyCode'));
4List<SampleNotificationRequest.NotificationItems> notificationItems = notificationRequest.notificationItems;
5SampleNotificationRequest.NotificationRequestItem notificationRequestItem = notificationItems[0].NotificationRequestItem;
6
7Boolean success = Boolean.valueOf(notificationRequestItem.success);
8String pspReference = notificationRequestItem.pspReference;
9String eventCode = notificationRequestItem.eventCode;
10Double amount = notificationRequestItem.amount.value;
11
12commercepayments.NotificationStatus notificationStatus = null;
13if (success) {
14 notificationStatus = commercepayments.NotificationStatus.Success;
15} else {
16 notificationStatus = commercepayments.NotificationStatus.Failed;
17}
18commercepayments.BaseNotification notification = null;
19if ('CAPTURE'.equals(eventCode)) {
20 notification = new commercepayments.CaptureNotification();
21} else if ('REFUND'.equals(eventCode)) {
22 notification = new commercepayments.ReferencedRefundNotification();
23}
24notification.setStatus(notificationStatus);
25notification.setGatewayReferenceNumber(pspReference);
26notification.setAmount(amount);1commercepayments.NotificationSaveResult saveResult = commercepayments.NotificationClient.record(notification);1commercepayments.GatewayNotificationResponse gnr = new commercepayments.GatewayNotificationResponse();
2if (saveResult.isSuccess()) {
3 system.debug('Notification accepted by platform');
4} else {
5 system.debug('Errors in the result '+ Blob.valueOf(saveResult.getErrorMessage()));
6}
7gnr.setStatusCode(200);
8gnr.setResponseBody(Blob.valueOf('[accepted]'));
9return gnr;デバッグ
通常、Apex デバッグログは開発者コンソールで使用できます。ただし、Salesforce では開発者コンソールの processNotification メソッドからのデバッグログが保存されません。system.debug を使用したメソッドフローのこの部分を確認するには、「デバッグログの設定」の「ゲストユーザのデバッグログの収集」セクションを参照してください。