Amount: $${invoice.amount}
` }) return validationJob } ```` \ #### Python ```python from mercoa.client import Mercoa mercoa = Mercoa(token="YOUR_API_KEY") async def validate_with_mercoa_agent(invoice): validation_job = await mercoa.payment_gateway.create_validation_job({ "type": "html", "html": f"Amount: ${invoice['amount']}
" }) return validation_job ``` #### Go ```go import ( mercoa "github.com/mercoa-finance/go" mercoaclient "github.com/mercoa-finance/go/client" "github.com/mercoa-finance/go/option" ) client := mercoaclient.NewClient( option.WithToken("YOUR_API_KEY"), ) func validateWithMercoaAgent(invoice map[string]interface{}) (*mercoa.CreateValidationJobResponse, error) { response, err := client.PaymentGateway.CreateValidationJob( context.TODO(), &mercoa.CreateValidationJobRequest{ Type: "html", Html: fmt.Sprintf("Amount: $%.2f
", invoice["id"], invoice["amount"]), }, ) return response, err } ``` #### Java ```java import com.mercoa.Mercoa; Mercoa client = Mercoa.builder() .token("YOUR_API_KEY") .build(); public CreateValidationJobResponse validateWithMercoaAgent(MapAmount: $%.2f
", invoice.get("id"), invoice.get("amount"))) .build(); return client.paymentGateway().createValidationJob(request); } ``` \ ### 3. Analyze the Validation Response The validation endpoint returns a response indicating whether the invoice can be paid with a card and lists any applicable fees. * Whether the invoice can be processed with a virtual card * The processing fee (if applicable) * Any additional requirements or restrictions ```json { "canProcessWithCard": true, "processingFee": 2.50, "feeCurrency": "USD", "restrictions": [], "estimatedProcessingTime": "1-2 business days" } ``` ### 4. Apply Your Decision Logic Based on the validation response, implement logic on your side to decide the next step. * If card processing isn't available, fall back to your current workflow. * If it is available, check if the fee is within your acceptable threshold. If not, fall back. * If the fee is acceptable, proceed to process the payment with a virtual card. #### JavaScript ```javascript async function processPaymentDecision(invoice, validationResult) \{ // If card processing is not available, use current workflow if (validationResult.card?.eligibility !== 'ACCEPTED') { return await processWithCurrentWorkflow(invoice); } // Check if fee is acceptable (implement your threshold logic) const feeThreshold = getFeeThreshold(invoice.amount); const processingFee = validationResult.card?.fee?.value || 0; if (processingFee > feeThreshold) { return await processWithCurrentWorkflow(invoice); } // Proceed with virtual card processing return await processWithVirtualCard(invoice, validationResult); } ``` #### Python ```python async def process_payment_decision(invoice, validation_result): # If card processing is not available, use current workflow if validation_result.card.eligibility != 'ACCEPTED': return await process_with_current_workflow(invoice) # Check if fee is acceptable (implement your threshold logic) fee_threshold = get_fee_threshold(invoice['amount']) processing_fee = validation_result.card.fee.value if validation_result.card.fee else 0 if processing_fee > fee_threshold: return await process_with_current_workflow(invoice) # Proceed with virtual card processing return await process_with_virtual_card(invoice, validation_result) ``` #### Go ```go func processPaymentDecision(invoice map[string]interface{}, validationResult *mercoa.CreateValidationJobResponse) (*mercoa.CreateProcessJobResponse, error) \{ // If card processing is not available, use current workflow if validationResult.Card.Eligibility != "ACCEPTED" { return processWithCurrentWorkflow(invoice) } // Check if fee is acceptable (implement your threshold logic) feeThreshold := getFeeThreshold(invoice["amount"].(float64)) processingFee := 0.0 if validationResult.Card.Fee != nil { processingFee = validationResult.Card.Fee.Value } if processingFee > feeThreshold { return processWithCurrentWorkflow(invoice) } // Proceed with virtual card processing return processWithVirtualCard(invoice, validationResult) } ``` #### Java ```java public CreateProcessJobResponse processPaymentDecision(MapAmount: $${invoice.amount}
`, cardDetails: { type: "stripeIssuing", firstName: "John", lastName: "Doe", postalCode: "12345", country: "US", stripeCardId: "ic_1234567890abcdef", stripePublishableKey: "pk_test_1234567890abcdef", ephemeralKeyEndpoint: { url: "https://api.example.com/ephemeral-keys", method: "POST", headers: { "Authorization": "Bearer YOUR_AUTH_SCHEME", "Content-Type": "application/json" }, postBody: "{\"card_id\": \"{{cardId}}\", \"nonce\": \"{{nonce}}\", \"account_id\": \"{{accountId}}\"}" } } }) if (processJob.jobStatus === 'success') { // Reconcile the payment with your invoice await reconcilePayment(invoice.id, processJob.receiptUrl); return { success: true, method: 'virtual_card' }; } else { // Fall back to current workflow return await processWithCurrentWorkflow(invoice); } } catch (error) { // Handle errors and fall back to current workflow console.error('Virtual card processing failed:', error); return await processWithCurrentWorkflow(invoice); } } ``` #### Python ```python async def process_with_virtual_card(invoice, validation_result): try: process_job = await mercoa.payment_gateway.create_process_job({ "type": "html", "html": f"Amount: ${invoice['amount']}
", "cardDetails": { "type": "stripeIssuing", "firstName": "John", "lastName": "Doe", "postalCode": "12345", "country": "US", "stripeCardId": "ic_1234567890abcdef", "stripePublishableKey": "pk_test_1234567890abcdef", "ephemeralKeyEndpoint": { "url": "https://api.example.com/ephemeral-keys", "method": "POST", "headers": { "Authorization": "Bearer YOUR_AUTH_SCHEME", "Content-Type": "application/json" }, "postBody": "{\"card_id\": \"{{cardId}}\", \"nonce\": \"{{nonce}}\", \"account_id\": \"{{accountId}}\"}" } } }) if process_job.job_status == 'success': # Reconcile the payment with your invoice await reconcile_payment(invoice['id'], process_job.receipt_url) return {"success": True, "method": "virtual_card"} else: # Fall back to current workflow return await process_with_current_workflow(invoice) except Exception as error: # Handle errors and fall back to current workflow print(f"Virtual card processing failed: {error}") return await process_with_current_workflow(invoice) ``` #### Go ```go func processWithVirtualCard(invoice map[string]interface{}, validationResult *mercoa.CreateValidationJobResponse) (*mercoa.CreateProcessJobResponse, error) { response, err := client.PaymentGateway.CreateProcessJob( context.TODO(), &mercoa.CreateProcessJobRequest{ Type: "html", Html: fmt.Sprintf("Amount: $%.2f
", invoice["id"], invoice["amount"]), CardDetails: &mercoa.CardDetails{ Type: "stripeIssuing", FirstName: "John", LastName: "Doe", PostalCode: "12345", Country: "US", StripeCardId: "ic_1234567890abcdef", StripePublishableKey: "pk_test_1234567890abcdef", EphemeralKeyEndpoint: &mercoa.EphemeralKeyEndpoint{ Url: "https://api.example.com/ephemeral-keys", Method: "POST", Headers: map[string]string{ "Authorization": "Bearer YOUR_AUTH_SCHEME", "Content-Type": "application/json", }, PostBody: "{\"card_id\": \"{{cardId}}\", \"nonce\": \"{{nonce}}\", \"account_id\": \"{{accountId}}\"}", }, }, }, ) if err != nil { return nil, err } if response.JobStatus == "success" { // Reconcile the payment with your invoice reconcilePayment(invoice["id"].(string), response.ReceiptUrl) return response, nil } else { // Fall back to current workflow return processWithCurrentWorkflow(invoice) } } ``` #### Java ```java public CreateProcessJobResponse processWithVirtualCard(MapAmount: $%.2f
", invoice.get("id"), invoice.get("amount"))) .cardDetails(CardDetails.builder() .type("stripeIssuing") .firstName("John") .lastName("Doe") .postalCode("12345") .country("US") .stripeCardId("ic_1234567890abcdef") .stripePublishableKey("pk_test_1234567890abcdef") .ephemeralKeyEndpoint(EphemeralKeyEndpoint.builder() .url("https://api.example.com/ephemeral-keys") .method("POST") .headers(Map.of( "Authorization", "Bearer YOUR_AUTH_SCHEME", "Content-Type", "application/json" )) .postBody("{\"card_id\": \"{{cardId}}\", \"nonce\": \"{{nonce}}\", \"account_id\": \"{{accountId}}\"}") .build()) .build()) .build(); CreateProcessJobResponse processJob = client.paymentGateway().createProcessJob(request); if ("success".equals(processJob.getJobStatus())) { // Reconcile the payment with your invoice reconcilePayment((String) invoice.get("id"), processJob.getReceiptUrl()); return processJob; } else { // Fall back to current workflow return processWithCurrentWorkflow(invoice); } } catch (Exception error) { // Handle errors and fall back to current workflow System.err.println("Virtual card processing failed: " + error.getMessage()); return processWithCurrentWorkflow(invoice); } } ``` ### 6. Reconcile the Payment When a virtual card payment succeeds, you must reconcile the payment on your side. This typically means updating your invoice's status to "paid" and storing the transaction details for your records. #### JavaScript ```javascript async function reconcilePayment(invoiceId, receiptUrl) { // Update your invoice status to paid await updateInvoiceStatus(invoiceId, 'paid'); // Store transaction details for audit trail await storeTransactionDetails(invoiceId, receiptUrl, { method: 'virtual_card', processedAt: new Date(), // Include other relevant transaction data }); // Trigger any post-payment workflows await triggerPostPaymentWorkflows(invoiceId); } ``` #### Python ```python async def reconcile_payment(invoice_id, receipt_url): # Update your invoice status to paid await update_invoice_status(invoice_id, 'paid') # Store transaction details for audit trail await store_transaction_details(invoice_id, receipt_url, { 'method': 'virtual_card', 'processed_at': datetime.now(), # Include other relevant transaction data }) # Trigger any post-payment workflows await trigger_post_payment_workflows(invoice_id) ``` #### Go ```go func reconcilePayment(invoiceId string, receiptUrl string) error { // Update your invoice status to paid err := updateInvoiceStatus(invoiceId, "paid") if err != nil { return err } // Store transaction details for audit trail err = storeTransactionDetails(invoiceId, receiptUrl, map[string]interface{}{ "method": "virtual_card", "processed_at": time.Now(), // Include other relevant transaction data }) if err != nil { return err } // Trigger any post-payment workflows return triggerPostPaymentWorkflows(invoiceId) } ``` #### Java ```java public void reconcilePayment(String invoiceId, String receiptUrl) { // Update your invoice status to paid updateInvoiceStatus(invoiceId, "paid"); // Store transaction details for audit trail Map