Skip to content

Fixes two bugs in the Payping driver - #353

Open
alireza-hadizadeh wants to merge 2 commits into
shetabit:masterfrom
alireza-hadizadeh:patch-1
Open

alireza-hadizadeh wants to merge 2 commits into
shetabit:masterfrom
alireza-hadizadeh:patch-1

Conversation

@alireza-hadizadeh

Copy link
Copy Markdown

Description

Fixes two bugs in the Payping driver:

  1. purchase() threw Undefined array key "paymentCode" on every successful transaction, because the response body's keys are lowercased before being read.
  2. verify() was still using the old v2 callback contract (reading refid from the query string, and sending only paymentRefId to the verification endpoint). Updated to match Payping's v3 API: reads paymentRefId from the data callback payload, and sends paymentCode and amount along with paymentRefId when verifying.

Motivation and context

1. purchase() — undefined array key

The raw JSON response string is passed through mb_strtolower() before json_decode():

$responseBody = mb_strtolower($response->getBody()->getContents());
$body = @json_decode($responseBody, true);

This lowercases the JSON keys along with the values, so a response like {"paymentCode": "abc123"} becomes {"paymentcode": "abc123"} after decoding. The code then tries to access $body['paymentCode'] (camelCase), which never exists in $body, causing:

Undefined array key "paymentCode"

This happens on every successful purchase request (HTTP 200), since the error-handling branch is skipped and execution falls straight into the broken key access. verify() already correctly used the lowercase $body['cardnumber'], which is consistent with this same behavior — purchase() was just missed.

2. verify() — outdated v2 callback contract

Payping's v3 API changed how the payment reference is returned on callback and what the verify request body requires. The driver was still reading refid from the query string and posting only paymentRefId. Per Payping's v3 documentation, the reference is now delivered as a JSON payload in the data param, and the verify request should also include paymentCode (the transaction ID from purchase()) and amount. The amount is converted to Toman using the same logic already used in purchase(), so the value sent during verification matches what was originally sent during purchase. A null-check was also added around the incoming callback data, since a missing/malformed payload previously caused an unhandled fatal error instead of a clean exception.

Note for reviewers: the verify() change alters the callback contract (source of refId moves from query string to the data payload). If any existing integrations relied on the old refid query param, this could be a breaking change for them depending on how Payping's callback behaves for accounts still effectively on the old flow — flagging this explicitly so maintainers can weigh in on whether it needs a major version bump or should support both formats during a transition period.

How has this been tested?

Manually tested against the live Payping purchase and verification endpoints in a Laravel app using this package.

  • Confirmed the raw purchase response contains paymentCode (camelCase) before lowercasing, and that using $body['paymentcode'] (lowercase) resolves the transaction ID correctly.
  • Confirmed the verify callback delivers the reference inside the data JSON payload per Payping's v3 docs, and that sending paymentRefId, paymentCode, and amount together completes verification successfully.

Screenshots (if appropriate)

N/A

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • I have read the CONTRIBUTING document.
  • My pull request addresses exactly one patch/feature.
  • I have created a branch for this patch/feature.
  • Each individual commit in the pull request is meaningful.
  • I have added tests to cover my changes.
  • If my change requires a change to the documentation, I have updated it accordingly.

 mb_strtolower() on the raw JSON response lowercases keys before decoding, so $body only ever contains "paymentcode", never "paymentCode".
- Reads paymentRefId from the JSON `data` callback param (v3),
  not the old `refid` query param
- Sends paymentCode and amount in the verify request, as required
  by v3 verification
- Applies the same Toman conversion used in purchase() so the
  verify amount matches what was originally sent
- Guards against a missing/malformed callback payload instead of
  fataling on a null property access
@alireza-hadizadeh alireza-hadizadeh changed the title Patch 1 Fixes two bugs in the Payping driver Jul 21, 2026
@khanzadimahdi

Copy link
Copy Markdown
Member

please resolve the conflicts. sorry for that. we introduced a large upgrade to support php8.4+ and it caused many conflicts on your PR.

@khanzadimahdi

Copy link
Copy Markdown
Member

hey @alireza-hadizadeh , could you please resolve the conflicts and make sure tests pass ? otherwise I have to close the PR!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants